Merge branch 'dev' into feature/lightship

pull/198/head
Michael Li 2 years ago
commit c2b8a68ca1
No known key found for this signature in database

@ -7,6 +7,7 @@ on:
- dev
- 'jc/**'
- 'feature/**'
- 'x/**'
paths:
- '**.go'
- 'go.mod'

@ -45,14 +45,20 @@ Web端
## 🛠 技术栈
PaoPao主要由以下优秀的开源项目/工具构建
* [Go](https://go.dev/)
* [Gin](https://gin-gonic.com/)
* [Zinc](https://zinclabs.io/)
PaoPao主要由以下优秀的开源项目/工具构建
#### 后端:
* [Go](https://go.dev/ 'go')
* [Gin](https://gin-gonic.com/ 'gin')
* [Mir](https://github.com/alimy/mir 'go-mir')
* [Buf](https://github.com/bufbuild/buf 'buf')
* [gRPC](https://github.com/grpc/grpc-go 'grpc-go')
* [Zinc](https://zinclabs.io/ 'zinc')
#### 前端:
* [Naive UI](https://www.naiveui.com/)
* [Vue.js](https://vuejs.org/)
* [Vite.js](https://vitejs.dev/)
* [tauri](https://github.com/tauri-apps/tauri 'tauri')
<!-- GETTING STARTED -->
## 🏗 快速开始
@ -487,6 +493,8 @@ feature/followship
feature/mir
feature/localoss
jc/alimy
x/sqlc
x/sqlx
```
**分支说明**
* 分支`main`是主分支也是paopao-ce的稳定版本发布分支只有经过内部测试没有重大bug出现的稳定代码才会推进到这个分支该分支主要由`beta`分支代码演进而来,原则上**只接受bug修复PR**。`rc版本/稳定版本` 发布都应该在`main`主分支中进行。
@ -494,6 +502,7 @@ jc/alimy
* 分支`dev`是开发分支,**不定期频繁更新**,接受 *新功能PR、代码优化PR、bug修复PR***新功能PR** 都应该首先提交给`dev`分支进行合并bug修复/代码优化 后 **冻结新功能** 将代码演进合并到`beta`分支。
* `feature/*`是新功能子分支,一般新功能子分支都是 *从`dev`开发分支fork出来的*;子功能分支 **只专注于该新功能** 代码的开发/优化,待开发接近内测阶段 *提交新功能PR给`dev`分支进行review/merge*,待新功能代码演进到`beta`分支后,原则上是可以删除该分支,但也可以保留到稳定版本发布。**该分支专注于新功能的开发只接受新功能的bug修复/优化PR**。
* `jc/*`是代码库维护者的开发分支一般包含一些局部优化或者bug修复代码有时可以直接将代码merge到`dev/beta`分支原则上不允许直接merge代码到`main`主分支。
* `x/*`是技术实验分支某些技术的引入需要经过具体的代码实现与真实场景的测评考量评估后如果某项技术适合引入到paopao-ce就fork出一个`feature/*`分支作为新功能引入到paopao-ce。一般一些比较激进的技术从`dev`分支fork出一个新的`x/*`分支各种尝试、考量、评估后或丢弃、或引入到paopao-ce。
**代码分支演进图**
![](docs/proposal/.assets/000-01.png)

@ -5,7 +5,8 @@ paopao-ce roadmap.
* [x] add `Friendship` feature
* [ ] add `Lightship` feature
* [ ] add `Sqlx` feature
* [ ] add new `Web` service
* [x] add new `Web` service
* [x] add `Frontend:Web` feature
* [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

@ -18,7 +18,7 @@ type Priv interface {
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)
VisibleTweet(*web.VisibleTweetReq) (*web.VisibleTweetResp, mir.Error)
StickTweet(*web.StickTweetReq) (*web.StickTweetResp, mir.Error)
LockTweet(*web.LockTweetReq) (*web.LockTweetResp, mir.Error)
CollectionTweet(*web.CollectionTweetReq) (*web.CollectionTweetResp, mir.Error)
@ -37,7 +37,7 @@ type PrivBinding interface {
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)
BindVisibleTweet(*gin.Context) (*web.VisibleTweetReq, mir.Error)
BindStickTweet(*gin.Context) (*web.StickTweetReq, mir.Error)
BindLockTweet(*gin.Context) (*web.LockTweetReq, mir.Error)
BindCollectionTweet(*gin.Context) (*web.CollectionTweetReq, mir.Error)
@ -56,7 +56,7 @@ type PrivRender interface {
RenderCreateCommentReply(*gin.Context, *web.CreateCommentReplyResp, mir.Error)
RenderDeleteComment(*gin.Context, mir.Error)
RenderCreateComment(*gin.Context, *web.CreateCommentResp, mir.Error)
RenderVisiblePost(*gin.Context, *web.VisiblePostResp, mir.Error)
RenderVisibleTweet(*gin.Context, *web.VisibleTweetResp, mir.Error)
RenderStickTweet(*gin.Context, *web.StickTweetResp, mir.Error)
RenderLockTweet(*gin.Context, *web.LockTweetResp, mir.Error)
RenderCollectionTweet(*gin.Context, *web.CollectionTweetResp, mir.Error)
@ -147,13 +147,13 @@ func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) {
default:
}
req, err := b.BindVisiblePost(c)
req, err := b.BindVisibleTweet(c)
if err != nil {
r.RenderVisiblePost(c, nil, err)
r.RenderVisibleTweet(c, nil, err)
return
}
resp, err := s.VisiblePost(req)
r.RenderVisiblePost(c, resp, err)
resp, err := s.VisibleTweet(req)
r.RenderVisibleTweet(c, resp, err)
})
router.Handle("POST", "/post/stick", func(c *gin.Context) {
@ -325,7 +325,7 @@ func (UnimplementedPrivServant) CreateComment(req *web.CreateCommentReq) (*web.C
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) VisiblePost(req *web.VisiblePostReq) (*web.VisiblePostResp, mir.Error) {
func (UnimplementedPrivServant) VisibleTweet(req *web.VisibleTweetReq) (*web.VisibleTweetResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
@ -388,7 +388,7 @@ func (r *UnimplementedPrivRender) RenderCreateComment(c *gin.Context, data *web.
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderVisiblePost(c *gin.Context, data *web.VisiblePostResp, err mir.Error) {
func (r *UnimplementedPrivRender) RenderVisibleTweet(c *gin.Context, data *web.VisibleTweetResp, err mir.Error) {
r.RenderAny(c, data, err)
}
@ -459,8 +459,8 @@ func (b *UnimplementedPrivBinding) BindCreateComment(c *gin.Context) (*web.Creat
return obj, err
}
func (b *UnimplementedPrivBinding) BindVisiblePost(c *gin.Context) (*web.VisiblePostReq, mir.Error) {
obj := new(web.VisiblePostReq)
func (b *UnimplementedPrivBinding) BindVisibleTweet(c *gin.Context) (*web.VisibleTweetReq, mir.Error) {
obj := new(web.VisibleTweetReq)
err := b.BindAny(c, obj)
return obj, err
}

@ -24,7 +24,7 @@ paopao-ce使用对象存储服务存储 图片/视频/附件 等推文资源。
* 本地(Native) - 部署OBS(Object Blob Storage System)
目前开发环境可以使用`localoss`功能提供简单的OBS服务, 也可以自行部署[MinIO](https://github.com/minio/minio)来提供对象存储服务。
* 云对象存储服务
* 云对象存储服务
阿里云、腾讯云、华为云都提供云对象存储服务,如何开启服务请参考相应文档进行部署。
#### 搜索引擎
@ -40,7 +40,7 @@ paopao-ce在代码实现上采用 **单体架构模式、分层设计、功能
## 从人文角度思考
现在的互联网世界已经非常精彩各种社交媒体平台琳琅满目使用体验也非常友好。每个社交平台都有自己的运营方式都有自己的核心用户群体也有自己的产品灵魂都在不断的进行生态演进。比如Twitter、微博都已经从最初的推文分享服务演进到一个成熟的传媒平台注册用户非常庞大日均访问PV也是一个惊人的数字这就注定了平台的运营思维是多维度考量均衡的结果只能做到让用户群体的大多数人用户体验友好并不能满足所有人的需求。大平台有大平台的运营模式小站点有小站点的维系空间。对于类似Twitter这样的推文分享服务paopao-ce提供一种小站点部署模式采用类似WordPress的运维模式**个人/小组织** 能快速、便捷的拥有一个提供推文分享服务的小站点,以填补那些在大平台下难以享受到的用户体验,享受小圈子内的自由空间。
就像许巍唱的「曾经的你」这首歌中所说:"曾梦想仗剑走天涯~ 看一看世界的繁华~ 年少的心总有些轻狂~ 如今你四海为家~ ......" 曾经的你我也在 疯狂刷朋友圈、狂奔微博空间、畅游Twitter世界但是随着环境的改变、岁月的洗礼、心路的淬炼后你我可能已经不复当年的热情逐渐淡出朋友圈、沦为微博的稀客或许Twitter世界还有点吸引力但是总感觉表达的欲望不复从前了。是什么原因变成这样的呢原因可能很多也各自有自己的不同情形所至于此。但是总归一条那就是 **自由**; 如果有那么一个有限空间内,可以自由的 *谈天说地、品头论足、唠唠叨叨亦或自言自语*你我是否又能燃起表达的激情呢从这个角度来说paopao-ce就很契合这种需求曾经你我想拥有一个自己的博客小站点而使用WordPress那么今天想拥有一个自己的类似Twitter的推文分享服务小站点部署paopao-ce或许也是一个不错的选择。
就像许巍唱的「曾经的你」这首歌中所说:*"曾梦想仗剑走天涯~ 看一看世界的繁华~ 年少的心总有些轻狂~ 如今你四海为家~ ......"* 曾经的你我也在 疯狂刷朋友圈、狂奔微博空间、畅游Twitter世界但是随着环境的改变、岁月的洗礼、心路的淬炼后你我可能已经不复当年的热情逐渐淡出朋友圈、沦为微博的稀客或许Twitter世界还有点吸引力但是总感觉表达的欲望不复从前了。是什么原因变成这样的呢原因可能很多也各自有自己的不同情形所至于此。但是总归一条那就是 **自由**; 如果有那么一个有限空间内,可以自由的 **谈天说地、品头论足、唠唠叨叨亦或自言自语**你我是否又能燃起表达的激情呢从这个角度来说paopao-ce就很契合这种需求曾经你我想拥有一个自己的博客小站点而使用WordPress那么今天想拥有一个自己的类似Twitter的推文分享服务小站点部署paopao-ce或许也是一个不错的选择。
一个产品应该有一个**属于自己的灵魂**,可以说 paopao-ce的宗旨就是 **打造一个清新文艺的微社区**。
@ -54,7 +54,7 @@ paopao-ce在代码实现上采用 **单体架构模式、分层设计、功能
1. paopao-ce在代码实现上为什么采用单体架构模式
一个项目的架构设计是多方面考量均衡的结果,最终的目的是满足项目的需求与长远发展。
* 从架构模式的角度来说单体架构模式可以满足paopao-ce对自身服务定位的需求完全有能力承载预期的用户流量QPS所以采用单体模式架构设计是没有问题的
* 从运营者的角度来说,在能保障服务质量的前提下,最看重的还是运营成本的考量。提供一项保质保量的服务,可持续性是评价一项服务的重要指标。单体架构模式的项目部署简单,成本相对于分布式架构模式的项目也更低,假设门槛也没有那么高。黑猫白猫,能抓老鼠就是好猫 在什么阶段就用什么技术,根据部署运营场景选择适合的技术来支撑服务,才是运营者明智的选择。
* 从运营者的角度来说,在能保障服务质量的前提下,最看重的还是运营成本的考量。提供一项保质保量的服务,可持续性是评价一项服务的重要指标。单体架构模式的项目部署简单,成本相对于分布式架构模式的项目也更低,架设门槛也没有那么高。*黑猫白猫,能抓老鼠就是好猫* 在什么阶段就用什么技术,根据部署运营场景选择适合的技术来支撑服务,才是运营者明智的选择。
* 现在不管是单体架构模式亦或是云原生的分布式架构模式相应的技术栈生态都已经非常成熟技术本身没有优劣之分需要根据具体环境来适配合适的技术这样才能在你保证服务质量的同时保证服务的可持续性与经济性。说白了就是paopao-ce目前采用单体架构模式的设计满足优质服务的同时性价比最高。
1. 如果一个paopao-ce部署站点运营一段时间后QPS逐渐提高到一定程度目前架构的paopao-ce无法满足进一步的用户流量冲击是否会采用分布式技术栈进行优化
不会。paopao-ce将保守的采用目前的单体架构模式提供极致的QPS用户体验如果确实需要超高QPS需求的实例部署将另起炉灶开发另一款相应的产品或许会采用云原生的分布式技术栈生态进行架构设计这将是另一个paopao产品的故事序章了(前提是paopao能火出圈)。

@ -1,6 +1,6 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 002| 北野 | 2022-11-04 | 2022-11-06 | v0.2 | 提议 |
| 002| 北野 | 2022-11-04 | 2023-01-04 | v1.0 | 提议 |
### Friendship功能项的设计概要
Friendship功能提供好友间分享推文信息的机制更好的帮助用户建立自己的推文分享小圈子。Friendship本质上想优化的是泡泡广场页面推文列表的生成机制开启功能后推文列表只能获取 `公开/私密/好友` 的推文,每个用户都有属于自己的个性化推文列表。在提供个性化推文列表生成机制的同时,好友体系的建立也顺便帮助用户建立自己的个性化有限范围内的灵魂社交小圈子,只有相互间拥有个性化认同感的用户才能互为好友。
@ -27,6 +27,8 @@ Friendship功能提供好友间分享推文信息的机制更好的帮助用
* 推文展示时标记推文的可见性描述;
#### 设计细节
* 参考实现(PR):
[add support Friendship feature #192](https://github.com/rocboss/paopao-ce/pull/192)
* 预览
@ -36,6 +38,7 @@ Friendship功能提供好友间分享推文信息的机制更好的帮助用
| ![](.assets/002-02.png)![](.assets/002-01.png)|
| ![](.assets/002-07.png)|
| ![](.assets/002-08.png)|
### 疑问
1. 什么是弱关系好友体系?
@ -58,4 +61,7 @@ Friendship功能提供好友间分享推文信息的机制更好的帮助用
* 初始文档
#### v0.2(2022-11-06) - 北野
* 添加初始文档内容
* 添加初始文档内容
#### v1.0(2023-01-04) - 北野
* 添加参考实现PR信息

@ -1,6 +1,6 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 005| 北野 | 2022-11-21 | 2022-12-10 | v1.0 | 提议 |
| 005| 北野 | 2022-11-21 | 2023-01-04 | v1.1 | 提议 |
### 引入go-mir优化后端架构设计
引入[github.com/alimy/mir/v3](https://github.com/alimy/mir)优化后端的架构设计,使得后端代码更具扩展型。
@ -16,6 +16,9 @@
依赖库:
* [go-mir](https://github.com/alimy/mir)
参考实现(PR):
* [引入go-mir重构paopao-ce的接入层与业务逻辑层 #196](https://github.com/rocboss/paopao-ce/pull/196)
### 疑问
1. 为什么引入go-mir
@ -35,3 +38,6 @@
#### v1.0(2022-12-10) - 北野
* 添加内容
#### v1.1(2023-01-04) - 北野
* 添加参考实现PR信息

@ -1,14 +1,62 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 006| 北野 | 2022-11-23 | 2022-12-23 | v0.1 | 提议 |
| 006| 北野 | 2022-11-23 | 2022-01-01 | v1.0 | 提议 |
### 关于paopao-ce的结构设计
本文档主要讨论paopao-ce目前的代码结构简要清晰的描述一个**API请求**从 **接受解析->逻辑处理->结果响应**的大概路径帮助开发人员快速了解paopao-ce代码基的基本面更好的融入paopao-ce的开发中做出PR贡献。
![](.assets/006-01.png)
### 两种服务 - RESTful API服务 与 gRPC服务
paopao-ce提供RESTful API与gRPC两种类型子服务并且拥有**单实例多服务运行**的机制。RESTful API服务基于[gin](https://github.com/gin-gonic/gin)引擎实现,使用[go-mir](https://github.com/alimy/mir)脚手架辅助工具集实现RESTFul API从接口定义到代码自动生成的便捷开发体验。 gRPC服务使用[buf](https://github.com/bufbuild/buf)自动化辅助工具对gRPC服务从 `*.proto` DSL服务接口定义到接口代码自动生成的全流程管理。
### 结构说明
paopao-ce采用清晰的分层结构设计主要包括 **接入层、业务逻辑层、数据逻辑层、数据存储**。
* 接入层
RESTful API服务的接入层由 [gin](https://github.com/gin-gonic/gin)引擎 与 [go-mir](https://github.com/alimy/mir)生成的 **Binding/Render** 代码共同组成。当一个HTTP Request被http server接受后通过[gin](https://github.com/gin-gonic/gin)的路由机制,由相应的[go-mir](https://github.com/alimy/mir)生成的`Binding`将请求解析后传入 **业务逻辑层**中相对应的 子服务Servants 完成业务处理后获得结果,[go-mir](https://github.com/alimy/mir)生成的`Render`把结果渲染后生成对应的 HTTP Response发送出去以完成一个HTTP请求。
gRPC服务的接入层由其对应的gRPC服务器引擎组成当一个RPC请求过来后先把请求解码解析后传入 **业务逻辑层**中相对应的 子服务Servers 完成业务处理后获得结果,将处理结果编码后生成对应的 HTTP Response发送出去就完成了一个RPC请求的完整流程。
* 业务逻辑层
RESTful API服务的业务逻辑层是由[go-mir](https://github.com/alimy/mir)依据接口定义自动生成的**Servants服务接口**组成开发人员需要实现这些接口以提供相应的业务逻辑。gRPC也是一样的业务逻辑需要通过实现gRPC依据proto DSL定义接口自动生成的服务接口来提供相应业务处理服务。
* 数据逻辑层
paopao-ce将所有与数据存储相关的服务都统一定义成接口包括**SQL服务、缓存服务、OBS服务、Search服务** 等然后根据具体的部署环境选择适配的相应存储服务实现。比如OBS服务定义了统一的操作对象存储的服务接口然后提供阿里云、腾讯云、华为云、MinIO、S3、Localoss等的服务适配实现这样就可以根据不同的部署环境切换使用不同的对象存储服务实现。
* 数据存储
数据存储包括 SQL存储(MySQL/PostgreSQL/Sqlite3)、Cache、OBS、Search Engine(Zinc/Meilisearch)等paopao-ce本身不关心具体的数据存储是如何部署的一般是通过对应的标准方式连接部署实例以获取相应存储服务。
### paopao-ce代码目录的说明
```sh
tree -L 2
.
|-- auto
| |-- api
| `-- rpc
|-- internal
| |-- conf
| |-- core
| |-- dao
| |-- ims
| |-- migration
| |-- model
| |-- obs
| |-- servants
| `-- service
|-- main.go
|-- mirc
|-- proto
|-- release
`-- web
```
* 根目录的`mirc`包含RESTful API的[go-mir](https://github.com/alimy/mir)服务接口定义文件, `auto/api`目录包含[go-mir](https://github.com/alimy/mir)自动生成的服务接口代码;
* 目录`proto`包含gRPC的proto服务接口定义文件自动生成的服务接口代码包含在`auto/rpc`目录中;
* 业务逻辑层的代码都包含在`internal/servants`目录包括RESTful服务以及gRPC服务的业务逻辑处理代码都包含在这个目录中
* `internal/core`包含所有数据逻辑层的服务接口定义,相应的数据逻辑层服务接口实现代码都包含在`internal/dao`目录中;
* 一些大的功能模块统一放置于`internal`目录中,以降低代码目录深度;比如数据库迁移功能模块`migration`的代码包含在`internal/migration`目录、 消息推送功能模块`ims` -> `internal/ims`, 简单本地OBS功能`obs` -> `internal/obs` 等;
* `internal/service`目录包含paopao-ce所有子服务(`Web`、`Admin`、`Bot`、`SpaceX`、`Mobile` ...)的初始化逻辑代码;
* `internal/conf`目录包含全局配置相关的逻辑代码;
### 疑问
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的生成代码有点类似。
**工欲善其事,必先利其器**。为了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秉持的代码开发原则之一。
@ -16,4 +64,6 @@ RESTful服务与gRPC服务各自有擅长的场景在合适的场景使用最
#### v0.0(2022-11-23) - 北野
* 初始文档, 先占个位置
#### v0.1(2022-12-23) - 北野
* 添加部分内容
* 添加部分内容
#### v1.0(2023-01-01) - 北野
* 添加部分内容

@ -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.4
github.com/alimy/mir/v3 v3.0.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

@ -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.4 h1:4++lea7OWmykHRVbF1nCnKOJXCvBifmnhe47e91aV6c=
github.com/alimy/mir/v3 v3.0.0-beta.4/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU=
github.com/alimy/mir/v3 v3.0.0 h1:bUcT+SLs/BYHIuHzTCbYnxnEwbYDSCDJULU5a1YZDes=
github.com/alimy/mir/v3 v3.0.0/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=

@ -48,7 +48,7 @@ func (t *Tag) Get(db *gorm.DB) (*Tag, error) {
err := db.First(&tag).Error
if err != nil {
return &tag, err
return nil, err
}
return &tag, nil
@ -88,7 +88,7 @@ func (t *Tag) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*
}
}
if err = db.Where("is_del = ?", 0).Find(&tags).Error; err != nil {
if err = db.Where("is_del = 0 and quote_num > 0").Find(&tags).Error; err != nil {
return nil, err
}

@ -83,7 +83,7 @@ type SuggestUsersReq struct {
}
type SuggestUsersResp struct {
Suggests []string `json:"suggests"`
Suggests []string `json:"suggest"`
}
type SuggestTagsReq struct {
@ -91,7 +91,7 @@ type SuggestTagsReq struct {
}
type SuggestTagsResp struct {
Suggests []string `json:"suggests"`
Suggests []string `json:"suggest"`
}
type TweetStarStatusReq struct {

@ -71,13 +71,13 @@ type StickTweetResp struct {
StickStatus int `json:"top_status"`
}
type VisiblePostReq struct {
type VisibleTweetReq struct {
BaseInfo `json:"-" binding:"-"`
ID int64 `json:"id" binding:"required"`
Visibility core.PostVisibleT `json:"visibility" binding:"required"`
ID int64 `json:"id"`
Visibility core.PostVisibleT `json:"visibility"`
}
type VisiblePostResp struct {
type VisibleTweetResp struct {
Visibility core.PostVisibleT `json:"visibility"`
}

@ -20,9 +20,7 @@ import (
"github.com/rocboss/paopao-ce/pkg/xerror"
)
type BaseServant struct {
// TODO
}
type BaseServant types.Empty
type DaoServant struct {
Redis *redis.Client

@ -627,11 +627,11 @@ func (s *privSrv) StarTweet(req *web.StarTweetReq) (*web.StarTweetResp, mir.Erro
}, nil
}
func (s *privSrv) VisiblePost(req *web.VisiblePostReq) (*web.VisiblePostResp, mir.Error) {
func (s *privSrv) VisibleTweet(req *web.VisibleTweetReq) (*web.VisibleTweetResp, mir.Error) {
if req.Visibility >= core.PostVisitInvalid {
return nil, xerror.InvalidParams
}
post, err := s.Ds.GetPostByID(req.User.ID)
post, err := s.Ds.GetPostByID(req.ID)
if err != nil {
return nil, _errVisblePostFailed
}
@ -639,7 +639,7 @@ func (s *privSrv) VisiblePost(req *web.VisiblePostReq) (*web.VisiblePostResp, mi
return nil, xerr
}
if err = s.Ds.VisiblePost(post, req.Visibility); err != nil {
logrus.Warnf("update post failure: %v", err)
logrus.Warnf("s.Ds.VisiblePost: %s", err)
return nil, _errVisblePostFailed
}
@ -647,7 +647,7 @@ func (s *privSrv) VisiblePost(req *web.VisiblePostReq) (*web.VisiblePostResp, mi
post.Visibility = req.Visibility
s.PushPostToSearch(post)
return &web.VisiblePostResp{
return &web.VisibleTweetResp{
Visibility: req.Visibility,
}, nil
}
@ -658,15 +658,15 @@ func (s *privSrv) StickTweet(req *web.StickTweetReq) (*web.StickTweetResp, mir.E
logrus.Errorf("Ds.GetPostByID err: %v\n", err)
return nil, _errStickPostFailed
}
if !req.User.IsAdmin {
return nil, _errNoPermission
}
newStatus := 1 - post.IsTop
if err = s.Ds.StickPost(post); err != nil {
return nil, _errStickPostFailed
}
return &web.StickTweetResp{
StickStatus: 1 - post.IsTop,
StickStatus: newStatus,
}, nil
}
@ -675,16 +675,15 @@ func (s *privSrv) LockTweet(req *web.LockTweetReq) (*web.LockTweetResp, mir.Erro
if err != nil {
return nil, _errLockPostFailed
}
if post.UserID != req.User.ID && !req.User.IsAdmin {
return nil, _errNoPermission
}
newStatus := 1 - post.IsLock
if err := s.Ds.LockPost(post); err != nil {
return nil, _errLockPostFailed
}
return &web.LockTweetResp{
LockStatus: 1 - post.IsLock,
LockStatus: newStatus,
}, nil
}

@ -169,7 +169,7 @@ func (s *pubSrv) TweetComments(req *web.TweetCommentsReq) (*web.TweetCommentsRes
// 获取总量
totalRows, _ := s.Ds.GetCommentCount(conditions)
resp := base.PageRespFrom(contents, req.Page, req.PageSize, totalRows)
resp := base.PageRespFrom(commentsFormated, req.Page, req.PageSize, totalRows)
return (*web.TweetCommentsResp)(resp), nil
}

@ -22,30 +22,28 @@ func Initialize() {
objectStorage = dao.ObjectStorageService()
if cfg.If("Alipay") {
initAlipay()
alipayClient = mustAlipayClient()
}
}
func initAlipay() {
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
}

@ -33,7 +33,7 @@ func (s *adminService) Version() *semver.Version {
}
func (s *adminService) OnInit() error {
s.registerRoute(servants.RegisterAdminServants)
s.registerRoute(s, servants.RegisterAdminServants)
return nil
}

@ -33,7 +33,7 @@ func (s *botService) Version() *semver.Version {
}
func (s *botService) OnInit() error {
s.registerRoute(servants.RegisterBotServants)
s.registerRoute(s, servants.RegisterBotServants)
return nil
}

@ -31,7 +31,7 @@ func (s *docsService) Version() *semver.Version {
}
func (s *docsService) OnInit() error {
s.registerRoute(servants.RegisterDocsServants)
s.registerRoute(s, servants.RegisterDocsServants)
return nil
}

@ -31,7 +31,7 @@ func (s *frontendWebService) Version() *semver.Version {
}
func (s *frontendWebService) OnInit() error {
s.registerRoute(servants.RegisterFrontendWebServants)
s.registerRoute(s, servants.RegisterFrontendWebServants)
return nil
}

@ -23,32 +23,10 @@ type grpcServer struct {
}
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
return s.server.Serve(s.listener)
}
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
}

@ -14,19 +14,17 @@ type baseGRPCService struct {
server *grpcServer
}
func (s *baseGRPCService) registerServer(h func(s *grpc.Server)) {
if s.server.status() != _statusServerStarted {
h(s.server.server)
}
func (s *baseGRPCService) registerServer(srv Service, h func(s *grpc.Server)) {
h(s.server.server)
s.server.addService(srv)
}
func (s *baseGRPCService) OnStart() error {
if err := s.server.start(); err != nil {
return err
}
// do nothing default
return nil
}
func (s *baseGRPCService) OnStop() error {
return s.server.stop()
// do nothing default
return nil
}

@ -24,34 +24,9 @@ type httpServer struct {
}
func (s *httpServer) 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.ListenAndServe(); err != nil {
s.Lock()
s.serverStatus = oldStatus
s.Unlock()
return err
}
return nil
return s.server.ListenAndServe()
}
func (s *httpServer) stop() error {
s.Lock()
defer s.Unlock()
if s.serverStatus == _statusServerStoped || s.serverStatus == _statusServerInitilized {
return nil
}
if err := s.server.Shutdown(context.Background()); err != nil {
return err
}
s.serverStatus = _statusServerStoped
return nil
return s.server.Shutdown(context.Background())
}

@ -14,19 +14,17 @@ type baseHttpService struct {
server *httpServer
}
func (s *baseHttpService) registerRoute(h func(e *gin.Engine)) {
if s.server.status() != _statusServerStarted {
h(s.server.e)
}
func (s *baseHttpService) registerRoute(srv Service, h func(e *gin.Engine)) {
h(s.server.e)
s.server.addService(srv)
}
func (s *baseHttpService) OnStart() error {
if err := s.server.start(); err != nil {
return err
}
// do nothing default
return nil
}
func (s *baseHttpService) OnStop() error {
return s.server.stop()
// do nothing default
return nil
}

@ -32,7 +32,7 @@ func (s *localossService) Version() *semver.Version {
}
func (s *localossService) OnInit() error {
s.registerRoute(servants.RegisterLocalossServants)
s.registerRoute(s, servants.RegisterLocalossServants)
return nil
}

@ -33,7 +33,7 @@ func (s *mobileService) Version() *semver.Version {
}
func (s *mobileService) OnInit() error {
s.registerServer(servants.RegisterMobileServants)
s.registerServer(s, servants.RegisterMobileServants)
return nil
}

@ -4,7 +4,15 @@
package service
import "sync"
import (
"fmt"
"sync"
"github.com/fatih/color"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/pkg/util"
)
var (
httpServers = newServerPool[*httpServer]()
@ -12,17 +20,16 @@ var (
)
const (
_statusServerUnknow uint8 = iota
_statusServerInitilized
_statusServerStarted
_statusServerStoped
actOnStart byte = iota
actOnStop
actStart
actStop
)
type server interface {
status() uint8
setStatus(uint8)
start() error
stop() error
services() []Service
}
type serverPool[T server] struct {
@ -30,8 +37,7 @@ type serverPool[T server] struct {
}
type baseServer struct {
sync.RWMutex
serverStatus uint8
ss map[string]Service
}
func (p *serverPool[T]) from(addr string, newServer func() T) T {
@ -40,23 +46,60 @@ func (p *serverPool[T]) from(addr string, newServer func() T) T {
return s
}
s = newServer()
s.setStatus(_statusServerInitilized)
p.servers[addr] = s
return s
}
func (s *baseServer) setStatus(status uint8) {
s.RLock()
defer s.RUnlock()
func (p *serverPool[T]) startServer(wg *sync.WaitGroup, maxSidSize int) {
for _, srv := range p.servers {
wg.Add(1)
go func(t T) {
ss := t.services()
if len(ss) < 1 {
return
}
for _, s := range ss {
colorPrint(actOnStart, s.OnStart(), maxSidSize, s)
}
colorPrint(actStart, t.start(), maxSidSize, ss...)
// remember to done sync.WaitGroup
wg.Done()
}(srv)
}
}
func (p *serverPool[T]) stopServer(maxSidSize int) {
for _, srv := range p.servers {
ss := srv.services()
if len(ss) < 1 {
return
}
for _, s := range ss {
colorPrint(actOnStop, s.OnStop(), maxSidSize, s)
}
colorPrint(actStop, srv.stop(), maxSidSize, ss...)
}
}
s.serverStatus = status
func (p *serverPool[T]) allServices() (ss []Service) {
for _, srv := range p.servers {
ss = append(ss, srv.services()...)
}
return
}
func (s *baseServer) status() uint8 {
s.RLock()
defer s.RUnlock()
func (s *baseServer) addService(srv Service) {
if srv != nil {
sid := srv.Name() + "@" + srv.Version().String()
s.ss[sid] = srv
}
}
return s.serverStatus
func (s *baseServer) services() (ss []Service) {
for _, s := range s.ss {
ss = append(ss, s)
}
return
}
func newServerPool[T server]() *serverPool[T] {
@ -67,7 +110,81 @@ func newServerPool[T server]() *serverPool[T] {
func newBaseServe() *baseServer {
return &baseServer{
RWMutex: sync.RWMutex{},
serverStatus: _statusServerUnknow,
ss: make(map[string]Service),
}
}
func checkServices() (int, int) {
var ss []Service
ss = append(ss, httpServers.allServices()...)
ss = append(ss, grpcServers.allServices()...)
return len(ss), maxSidSize(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 colorPrint(act byte, err error, l int, ss ...Service) {
s := ss[0]
switch act {
case actOnStart:
if err == nil {
fmt.Fprintf(color.Output, "%s [start] - %s", util.SidStr(s.Name(), s.Version(), l), s)
} else {
fmt.Fprintf(color.Output, "%s [start] - run OnStart error: %s\n", util.SidStr(s.Name(), s.Version(), l), err)
}
case actOnStop:
if err == nil {
fmt.Fprintf(color.Output, "%s [stop] - finish...\n", util.SidStr(s.Name(), s.Version(), l))
} else {
fmt.Fprintf(color.Output, "%s [stop] - run OnStop error: %s\n", util.SidStr(s.Name(), s.Version(), l), err)
}
case actStart:
if err != nil {
for _, s = range ss {
fmt.Fprintf(color.Output, "%s [start] - starting server occurs error: %s\n", util.SidStr(s.Name(), s.Version(), l), err)
}
}
case actStop:
if err != nil {
for _, s = range ss {
fmt.Fprintf(color.Output, "%s [stop] - stopping server occurs error: %s\n", util.SidStr(s.Name(), s.Version(), l), err)
}
}
}
}
// Start start all servers
func Start(wg *sync.WaitGroup) {
srvSize, maxSidSize := checkServices()
if srvSize < 1 {
return
}
// some initialize for server engine
gin.SetMode(conf.RunMode())
// start servers
httpServers.startServer(wg, maxSidSize)
grpcServers.startServer(wg, maxSidSize)
}
// Stop stop all servers
func Stop() {
srvSize, maxSidSize := checkServices()
if srvSize < 1 {
return
}
// stop servers
httpServers.stopServer(maxSidSize)
grpcServers.stopServer(maxSidSize)
}

@ -34,8 +34,8 @@ func (baseService) String() string {
return ""
}
// InitService Initial service
func InitService() []Service {
// MustInitService Initial service
func MustInitService() []Service {
ss := newService()
for _, s := range ss {
if err := s.OnInit(); err != nil {
@ -45,18 +45,6 @@ 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) {
// add all service if declared in features on config.yaml
cfg.In(cfg.Actions{

@ -33,7 +33,7 @@ func (s *spaceXService) Version() *semver.Version {
}
func (s *spaceXService) OnInit() error {
s.registerRoute(servants.RegisterSpaceXServants)
s.registerRoute(s, servants.RegisterSpaceXServants)
return nil
}

@ -33,7 +33,7 @@ func (s *webService) Version() *semver.Version {
}
func (s *webService) OnInit() error {
s.registerRoute(servants.RegisterWebServants)
s.registerRoute(s, servants.RegisterWebServants)
return nil
}
@ -88,7 +88,6 @@ func newWebService() Service {
},
}
})
return &webService{
baseHttpService: &baseHttpService{
server: server,

@ -31,7 +31,7 @@ func (s *oldWebService) Version() *semver.Version {
}
func (s *oldWebService) OnInit() error {
s.registerRoute(routers.RegisterRoute)
s.registerRoute(s, routers.RegisterRoute)
return nil
}

@ -14,7 +14,6 @@ import (
"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/service"
@ -53,52 +52,29 @@ func flagParse() {
flag.Parse()
}
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", util.SidStr(s.Name(), s.Version(), l), s)
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()
}(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
// 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")
l := service.MaxSidSize(ss)
for _, s := range ss {
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))
}
wg.Done()
}
func main() {
util.PrintHelloBanner(debug.VersionInfo())
if ss := service.InitService(); len(ss) > 0 {
wg := &sync.WaitGroup{}
wg.Add(len(ss) + 1)
runService(wg, ss)
go runManage(wg, ss)
wg.Wait()
} else {
ss := service.MustInitService()
if len(ss) < 1 {
fmt.Fprintln(color.Output, "no service need start so just exit")
return
}
wg := &sync.WaitGroup{}
// start services
fmt.Fprintf(color.Output, "\nstarting run service...\n\n")
service.Start(wg)
// graceful stop services
wg.Add(1)
go func() {
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")
service.Stop()
wg.Done()
}()
wg.Wait()
}

@ -1,10 +1,10 @@
### RESTful API for paopao-ce
本目录包含所有RESTful API相关定义文件
|目录|系列API|备注|
| ----- | ----- | ----- |
|web|/|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相关定义文件|
|服务|目录|系列API| url前缀|备注|
| ----- | ----- | ----- | ----- | ----- |
|Web|web|/|/|Web系列RESTful API相关定义文件|
|Admin|admin|m|/m/|Admin后台运维系列相关RESTful API相关定义文件|
|SpaceX|space|x|/x/|SpaceX系列相关RESTful API相关定义文件|
|NativeOBS|localoss|s|/s/| NativeOBS系列RESTful API相关定义文件|
|Bot|bot|r| /r/|Bot系列相关RESTful API相关定义文件|

@ -42,8 +42,8 @@ type Priv struct {
// StickTweet 置顶动态
StickTweet func(Post, web.StickTweetReq) web.StickTweetResp `mir:"/post/stick"`
// VisiblePost 修改动态可见度
VisiblePost func(Post, web.VisiblePostReq) web.VisiblePostResp `mir:"/post/visibility"`
// VisibleTweet 修改动态可见度
VisibleTweet func(Post, web.VisibleTweetReq) web.VisibleTweetResp `mir:"/post/visibility"`
// CreateTweetComment 发布动态评论
CreateComment func(Post, web.CreateCommentReq) web.CreateCommentResp `mir:"/post/comment"`

File diff suppressed because one or more lines are too long

@ -0,0 +1,48 @@
import{k as M,cm as O,cn as u,m as v,c as P,f as i,e as H,bM as N,b as V,d as K,u as D,x as E,j as G,y as $,bm as q,z as c,A as J,r as Q,h as s,bd as U,co as X,L as Y,B as Z,bK as oo,N as eo,bG as ro,bH as no,bI as lo,bF as so}from"./index.d4f5aad2.js";const to=r=>{const{lineHeight:e,borderRadius:d,fontWeightStrong:C,baseColor:t,dividerColor:b,actionColor:S,textColor1:g,textColor2:l,closeColorHover:h,closeColorPressed:f,closeIconColor:m,closeIconColorHover:p,closeIconColorPressed:n,infoColor:o,successColor:I,warningColor:x,errorColor:z,fontSize:T}=r;return Object.assign(Object.assign({},O),{fontSize:T,lineHeight:e,titleFontWeight:C,borderRadius:d,border:`1px solid ${b}`,color:S,titleTextColor:g,iconColor:l,contentTextColor:l,closeBorderRadius:d,closeColorHover:h,closeColorPressed:f,closeIconColor:m,closeIconColorHover:p,closeIconColorPressed:n,borderInfo:`1px solid ${u(t,v(o,{alpha:.25}))}`,colorInfo:u(t,v(o,{alpha:.08})),titleTextColorInfo:g,iconColorInfo:o,contentTextColorInfo:l,closeColorHoverInfo:h,closeColorPressedInfo:f,closeIconColorInfo:m,closeIconColorHoverInfo:p,closeIconColorPressedInfo:n,borderSuccess:`1px solid ${u(t,v(I,{alpha:.25}))}`,colorSuccess:u(t,v(I,{alpha:.08})),titleTextColorSuccess:g,iconColorSuccess:I,contentTextColorSuccess:l,closeColorHoverSuccess:h,closeColorPressedSuccess:f,closeIconColorSuccess:m,closeIconColorHoverSuccess:p,closeIconColorPressedSuccess:n,borderWarning:`1px solid ${u(t,v(x,{alpha:.33}))}`,colorWarning:u(t,v(x,{alpha:.08})),titleTextColorWarning:g,iconColorWarning:x,contentTextColorWarning:l,closeColorHoverWarning:h,closeColorPressedWarning:f,closeIconColorWarning:m,closeIconColorHoverWarning:p,closeIconColorPressedWarning:n,borderError:`1px solid ${u(t,v(z,{alpha:.25}))}`,colorError:u(t,v(z,{alpha:.08})),titleTextColorError:g,iconColorError:z,contentTextColorError:l,closeColorHoverError:h,closeColorPressedError:f,closeIconColorError:m,closeIconColorHoverError:p,closeIconColorPressedError:n})},io={name:"Alert",common:M,self:to};var ao=io,co=P("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;
word-break: break-word;
`,[i("border",`
border-radius: inherit;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
transition: border-color .3s var(--n-bezier);
border: var(--n-border);
pointer-events: none;
`),H("closable",[P("alert-body",[i("title",`
padding-right: 24px;
`)])]),i("icon",{color:"var(--n-icon-color)"}),P("alert-body",{padding:"var(--n-padding)"},[i("title",{color:"var(--n-title-text-color)"}),i("content",{color:"var(--n-content-text-color)"})]),N({originalTransition:"transform .3s var(--n-bezier)",enterToProps:{transform:"scale(1)"},leaveToProps:{transform:"scale(0.9)"}}),i("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);
`),i("close",`
transition:
color .3s var(--n-bezier),
background-color .3s var(--n-bezier);
position: absolute;
right: 0;
top: 0;
margin: var(--n-close-margin);
`),H("show-icon",[P("alert-body",{paddingLeft:"calc(var(--n-icon-margin-left) + var(--n-icon-size) + var(--n-icon-margin-right))"})]),P("alert-body",`
border-radius: var(--n-border-radius);
transition: border-color .3s var(--n-bezier);
`,[i("title",`
transition: color .3s var(--n-bezier);
font-size: 16px;
line-height: 19px;
font-weight: var(--n-title-font-weight);
`,[V("& +",[i("content",{marginTop:"9px"})])]),i("content",{transition:"color .3s var(--n-bezier)",fontSize:"var(--n-font-size)"})]),i("icon",{transition:"color .3s var(--n-bezier)"})]);const go=Object.assign(Object.assign({},E.props),{title:String,showIcon:{type:Boolean,default:!0},type:{type:String,default:"default"},bordered:{type:Boolean,default:!0},closable:Boolean,onClose:Function,onAfterLeave:Function,onAfterHide:Function});var uo=K({name:"Alert",inheritAttrs:!1,props:go,setup(r){const{mergedClsPrefixRef:e,mergedBorderedRef:d,inlineThemeDisabled:C,mergedRtlRef:t}=D(r),b=E("Alert","-alert",co,ao,r,e),S=G("Alert",t,e),g=$(()=>{const{common:{cubicBezierEaseInOut:n},self:o}=b.value,{fontSize:I,borderRadius:x,titleFontWeight:z,lineHeight:T,iconSize:R,iconMargin:y,iconMarginRtl:_,closeIconSize:A,closeBorderRadius:W,closeSize:w,closeMargin:B,closeMarginRtl:L,padding:k}=o,{type:a}=r,{left:j,right:F}=q(y);return{"--n-bezier":n,"--n-color":o[c("color",a)],"--n-close-icon-size":A,"--n-close-border-radius":W,"--n-close-color-hover":o[c("closeColorHover",a)],"--n-close-color-pressed":o[c("closeColorPressed",a)],"--n-close-icon-color":o[c("closeIconColor",a)],"--n-close-icon-color-hover":o[c("closeIconColorHover",a)],"--n-close-icon-color-pressed":o[c("closeIconColorPressed",a)],"--n-icon-color":o[c("iconColor",a)],"--n-border":o[c("border",a)],"--n-title-text-color":o[c("titleTextColor",a)],"--n-content-text-color":o[c("contentTextColor",a)],"--n-line-height":T,"--n-border-radius":x,"--n-font-size":I,"--n-title-font-weight":z,"--n-icon-size":R,"--n-icon-margin":y,"--n-icon-margin-rtl":_,"--n-close-size":w,"--n-close-margin":B,"--n-close-margin-rtl":L,"--n-padding":k,"--n-icon-margin-left":j,"--n-icon-margin-right":F}}),l=C?J("alert",$(()=>r.type[0]),g,r):void 0,h=Q(!0),f=()=>{const{onAfterLeave:n,onAfterHide:o}=r;n&&n(),o&&o()};return{rtlEnabled:S,mergedClsPrefix:e,mergedBordered:d,visible:h,handleCloseClick:()=>{var n;Promise.resolve((n=r.onClose)===null||n===void 0?void 0:n.call(r)).then(o=>{o!==!1&&(h.value=!1)})},handleAfterLeave:()=>{f()},mergedTheme:b,cssVars:C?void 0:g,themeClass:l==null?void 0:l.themeClass,onRender:l==null?void 0:l.onRender}},render(){var r;return(r=this.onRender)===null||r===void 0||r.call(this),s(oo,{onAfterLeave:this.handleAfterLeave},{default:()=>{const{mergedClsPrefix:e,$slots:d}=this,C={class:[`${e}-alert`,this.themeClass,this.closable&&`${e}-alert--closable`,this.showIcon&&`${e}-alert--show-icon`,this.rtlEnabled&&`${e}-alert--rtl`],style:this.cssVars,role:"alert"};return this.visible?s("div",Object.assign({},U(this.$attrs,C)),this.closable&&s(X,{clsPrefix:e,class:`${e}-alert__close`,onClick:this.handleCloseClick}),this.bordered&&s("div",{class:`${e}-alert__border`}),this.showIcon&&s("div",{class:`${e}-alert__icon`,"aria-hidden":"true"},Y(d.icon,()=>[s(eo,{clsPrefix:e},{default:()=>{switch(this.type){case"success":return s(so,null);case"info":return s(lo,null);case"warning":return s(no,null);case"error":return s(ro,null);default:return null}}})])),s("div",{class:[`${e}-alert-body`,this.mergedBordered&&`${e}-alert-body--bordered`]},Z(d.header,t=>{const b=t||this.title;return b?s("div",{class:`${e}-alert-body__title`},b):null}),d.default&&s("div",{class:`${e}-alert-body__content`},d))):null}})}});export{uo as _};

@ -0,0 +1 @@
import{_ as B}from"./post-skeleton.38f0f247.js";import{_ as N}from"./main-nav.3167f221.js";import{ai as z,d as E,r as a,a2 as R,Y as t,a4 as o,a5 as c,aj as S,W as n,a3 as m,a7 as l,ab as V,ac as F,$ as P,a6 as $,Z as s,aa as _,cb as j}from"./index.d4f5aad2.js";import{f as q}from"./formatTime.e07969bb.js";import{_ as D}from"./List.a66e9ae7.js";import{_ as I}from"./Pagination.c13c2d34.js";import{a as L,_ as M}from"./Skeleton.e1c16fcb.js";const O={key:0,class:"pagination-wrap"},T={key:0,class:"skeleton-wrap"},U={key:1},W={key:0,class:"empty-wrap"},Y={class:"bill-line"},Z=E({__name:"Anouncement",setup(G){const d=P(),g=S(),v=a(!1),u=a([]),r=a(+g.query.p||1),f=a(20),p=a(0),h=i=>{r.value=i};return R(()=>{}),(i,H)=>{const y=N,k=I,x=B,w=L,C=M,A=D;return n(),t("div",null,[o(y,{title:"\u516C\u544A"}),o(A,{class:"main-content-wrap",bordered:""},{footer:c(()=>[p.value>1?(n(),t("div",O,[o(k,{page:r.value,"onUpdate:page":h,"page-slot":m(d).state.collapsedRight?5:8,"page-count":p.value},null,8,["page","page-slot","page-count"])])):l("",!0)]),default:c(()=>[v.value?(n(),t("div",T,[o(x,{num:f.value},null,8,["num"])])):(n(),t("div",U,[u.value.length===0?(n(),t("div",W,[o(w,{size:"large",description:"\u6682\u65E0\u6570\u636E"})])):l("",!0),(n(!0),t(V,null,F(u.value,e=>(n(),$(C,{key:e.id},{default:c(()=>[s("div",Y,[s("div",null,"NO."+_(e.id),1),s("div",null,_(e.reason),1),s("div",{class:j({income:e.change_amount>=0,out:e.change_amount<0})},_((e.change_amount>0?"+":"")+(e.change_amount/100).toFixed(2)),3),s("div",null,_(m(q)(e.created_on)),1)])]),_:2},1024))),128))]))]),_:1})])}}});var te=z(Z,[["__scopeId","data-v-543914f4"]]);export{te as default};

@ -0,0 +1 @@
import{_ as z}from"./post-item.11c28084.js";import{_ as B}from"./post-skeleton.38f0f247.js";import{_ as E}from"./main-nav.3167f221.js";import{ai as P,d as R,r as n,a2 as $,Y as o,a4 as a,a5 as p,aj as b,cu as F,W as e,a3 as M,a7 as m,ab as N,ac as S,$ as V,al as j,a6 as q}from"./index.d4f5aad2.js";import{_ as I}from"./List.a66e9ae7.js";import{_ as L}from"./Pagination.c13c2d34.js";import{a as T,_ as U}from"./Skeleton.e1c16fcb.js";import"./content.ed80294a.js";import"./formatTime.e07969bb.js";import"./Thing.d394adea.js";const W={key:0,class:"pagination-wrap"},Y={key:0,class:"skeleton-wrap"},A={key:1},D={key:0,class:"empty-wrap"},G=R({__name:"Collection",setup(H){const d=V(),g=b();j();const s=n(!1),_=n([]),l=n(+g.query.p||1),c=n(20),u=n(0),r=()=>{s.value=!0,F({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 $(()=>{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":M(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",Y,[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(N,null,S(_.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};

@ -0,0 +1 @@
import{ai as k,d as C,al as E,W as e,Y as n,Z as c,a4 as o,aa as v,ae as N,r as l,a2 as P,cv as R,a5 as g,aj as S,a3 as U,a7 as y,ab as V,ac as q,$ as M,a6 as T}from"./index.d4f5aad2.js";import{_ as j}from"./post-skeleton.38f0f247.js";import{_ as F}from"./main-nav.3167f221.js";import{_ as L}from"./List.a66e9ae7.js";import{_ as W}from"./Pagination.c13c2d34.js";import{a as Y,_ as Z}from"./Skeleton.e1c16fcb.js";const A={class:"avatar"},G={class:"base-info"},H={class:"username"},J={class:"uid"},K=C({__name:"contact-item",props:{contact:null},setup(s){const p=E(),m=t=>{p.push({name:"user",query:{username:t}})};return(t,a)=>{const _=N;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({__name:"Contacts",setup(s){const p=M(),m=S(),t=l(!1),a=l([]),_=l(+m.query.p||1),u=l(20),d=l(0),w=r=>{_.value=r,f()};P(()=>{f()});const f=(r=!1)=>{a.value.length===0&&(t.value=!0),R({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 $=F,x=W,B=j,b=Y,z=O,I=Z,D=L;return e(),n("div",null,[o($,{title:"\u597D\u53CB"}),o(D,{class:"main-content-wrap",bordered:""},{footer:g(()=>[d.value>1?(e(),n("div",Q,[o(x,{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(V,null,q(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};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,56 @@
import{c as t,b as r,f as o,d as a,u as d,g as s,h as p}from"./index.d4f5aad2.js";var n=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",n,e),{mergedClsPrefix:e}},render(){const{mergedClsPrefix:i}=this;return p("div",{class:`${i}-input-group`},this.$slots)}});export{u as _};

@ -0,0 +1,73 @@
import{b as a,c as l,e as d,f as n,aB as w,aC as P,d as B,u as D,j,x as v,p as E,t as M,y as H,A as L,h as t,n as I,aD as O}from"./index.d4f5aad2.js";var T=a([l("list",`
--n-merged-border-color: var(--n-border-color);
--n-merged-color: var(--n-color);
--n-merged-color-hover: var(--n-color-hover);
margin: 0;
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);
`,[d("show-divider",[l("list-item",[a("&:not(:last-child)",[n("divider",`
background-color: var(--n-merged-border-color);
`)])])]),d("clickable",[l("list-item",`
cursor: pointer;
`)]),d("bordered",`
border: 1px solid var(--n-merged-border-color);
border-radius: var(--n-border-radius);
`),d("hoverable",[l("list-item",`
border-radius: var(--n-border-radius);
`,[a("&:hover",`
background-color: var(--n-merged-color-hover);
`,[n("divider",`
background-color: transparent;
`)])])]),d("bordered, hoverable",[l("list-item",`
padding: 12px 20px;
`),n("header, footer",`
padding: 12px 20px;
`)]),n("header, footer",`
padding: 12px 0;
box-sizing: border-box;
transition: border-color .3s var(--n-bezier);
`,[a("&:not(:last-child)",`
border-bottom: 1px solid var(--n-merged-border-color);
`)]),l("list-item",`
position: relative;
padding: 12px 0;
box-sizing: border-box;
display: flex;
flex-wrap: nowrap;
align-items: center;
transition:
background-color .3s var(--n-bezier),
border-color .3s var(--n-bezier);
`,[n("prefix",`
margin-right: 20px;
flex: 0;
`),n("suffix",`
margin-left: 20px;
flex: 0;
`),n("main",`
flex: 1;
`),n("divider",`
height: 1px;
position: absolute;
bottom: 0;
left: 0;
right: 0;
background-color: transparent;
transition: background-color .3s var(--n-bezier);
pointer-events: none;
`)])]),w(l("list",`
--n-merged-color-hover: var(--n-color-hover-modal);
--n-merged-color: var(--n-color-modal);
--n-merged-border-color: var(--n-border-color-modal);
`)),P(l("list",`
--n-merged-color-hover: var(--n-color-hover-popover);
--n-merged-color: var(--n-color-popover);
--n-merged-border-color: var(--n-border-color-popover);
`))]);const V=Object.assign(Object.assign({},v.props),{size:{type:String,default:"medium"},bordered:Boolean,clickable:Boolean,hoverable:Boolean,showDivider:{type:Boolean,default:!0}}),K=I("n-list");var A=B({name:"List",props:V,setup(e){const{mergedClsPrefixRef:o,inlineThemeDisabled:r,mergedRtlRef:s}=D(e),b=j("List",s,o),m=v("List","-list",T,O,e,o);E(K,{showDividerRef:M(e,"showDivider"),mergedClsPrefixRef:o});const c=H(()=>{const{common:{cubicBezierEaseInOut:p},self:{fontSize:h,textColor:u,color:g,colorModal:f,colorPopover:x,borderColor:z,borderColorModal:C,borderColorPopover:R,borderRadius:k,colorHover:y,colorHoverModal:_,colorHoverPopover:$}}=m.value;return{"--n-font-size":h,"--n-bezier":p,"--n-text-color":u,"--n-color":g,"--n-border-radius":k,"--n-border-color":z,"--n-border-color-modal":C,"--n-border-color-popover":R,"--n-color-modal":f,"--n-color-popover":x,"--n-color-hover":y,"--n-color-hover-modal":_,"--n-color-hover-popover":$}}),i=r?L("list",void 0,c,e):void 0;return{mergedClsPrefix:o,rtlEnabled:b,cssVars:r?void 0:c,themeClass:i==null?void 0:i.themeClass,onRender:i==null?void 0:i.onRender}},render(){var e;const{$slots:o,mergedClsPrefix:r,onRender:s}=this;return s==null||s(),t("ul",{class:[`${r}-list`,this.rtlEnabled&&`${r}-list--rtl`,this.bordered&&`${r}-list--bordered`,this.showDivider&&`${r}-list--show-divider`,this.hoverable&&`${r}-list--hoverable`,this.clickable&&`${r}-list--clickable`,this.themeClass],style:this.cssVars},o.header?t("div",{class:`${r}-list__header`},o.header()):null,(e=o.default)===null||e===void 0?void 0:e.call(o),o.footer?t("div",{class:`${r}-list__footer`},o.footer()):null)}});export{A as _,K as l};

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
import{d as e,W as o,Y as s,Z as r}from"./index.d4f5aad2.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};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
.reply-compose-wrap .reply-switch[data-v-3616e66c]{text-align:right;font-size:12px;margin:10px 0}.reply-compose-wrap .reply-switch .show[data-v-3616e66c]{color:#18a058;cursor:pointer}.reply-compose-wrap .reply-switch .hide[data-v-3616e66c]{opacity:.75;cursor:pointer}.reply-item[data-v-1e3df20d]{display:flex;flex-direction:column;font-size:12px;padding:8px;border-bottom:1px solid #f3f3f3}.reply-item .header-wrap[data-v-1e3df20d]{display:flex;align-items:center;justify-content:space-between}.reply-item .header-wrap .username[data-v-1e3df20d]{max-width:50%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.reply-item .header-wrap .username .reply-name[data-v-1e3df20d]{margin:0 3px;opacity:.75}.reply-item .header-wrap .timestamp[data-v-1e3df20d]{opacity:.75;text-align:right;display:flex;align-items:center;max-width:50%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.reply-item .base-wrap[data-v-1e3df20d]{display:flex}.reply-item .base-wrap .content[data-v-1e3df20d]{width:calc(100% - 40px);margin-top:4px;font-size:12px;text-align:justify;line-height:2}.reply-item .base-wrap .reply-switch[data-v-1e3df20d]{width:40px;text-align:right;font-size:12px;margin:10px 0 0}.reply-item .base-wrap .reply-switch .show[data-v-1e3df20d]{color:#18a058;cursor:pointer}.reply-item .base-wrap .reply-switch .hide[data-v-1e3df20d]{opacity:.75;cursor:pointer}.dark .reply-item[data-v-1e3df20d]{border-bottom:1px solid #262628}.comment-item[data-v-6b2cb186]{width:100%;padding:16px;box-sizing:border-box}.comment-item .nickname-wrap[data-v-6b2cb186]{font-size:14px}.comment-item .username-wrap[data-v-6b2cb186]{font-size:14px;opacity:.75}.comment-item .opt-wrap[data-v-6b2cb186]{display:flex;align-items:center}.comment-item .opt-wrap .timestamp[data-v-6b2cb186]{opacity:.75;font-size:12px}.comment-item .opt-wrap .del-btn[data-v-6b2cb186]{margin-left:4px}.comment-item .comment-text[data-v-6b2cb186]{display:block;text-align:justify;overflow:hidden;white-space:pre-wrap;word-break:break-all}.comment-item .opt-item[data-v-6b2cb186]{display:flex;align-items:center;opacity:.7}.comment-item .opt-item .opt-item-icon[data-v-6b2cb186]{margin-right:10px}.reply-wrap[data-v-6b2cb186]{margin-top:10px;border-radius:5px;background:#fafafc}.reply-wrap .reply-item[data-v-6b2cb186]:last-child{border-bottom:none}.dark .reply-wrap[data-v-6b2cb186]{background:#18181c}.compose-wrap[data-v-0702a552]{width:100%;padding:16px;box-sizing:border-box}.compose-wrap .compose-line[data-v-0702a552]{display:flex;flex-direction:row}.compose-wrap .compose-line .compose-user[data-v-0702a552]{width:42px;height:42px;display:flex;align-items:center}.compose-wrap .compose-line.compose-options[data-v-0702a552]{margin-top:6px;padding-left:42px;display:flex;justify-content:space-between}.compose-wrap .compose-line.compose-options .submit-wrap[data-v-0702a552]{display:flex;align-items:center}.compose-wrap .compose-line.compose-options .submit-wrap .cancel-btn[data-v-0702a552]{margin-right:8px}.compose-wrap .login-wrap[data-v-0702a552]{display:flex;justify-content:center;width:100%}.compose-wrap .login-wrap .login-banner[data-v-0702a552]{margin-bottom:12px;opacity:.8}.compose-wrap .login-wrap button[data-v-0702a552]{margin:0 4px}.attachment[data-v-0702a552]{display:flex;align-items:center}.attachment .text-statistic[data-v-0702a552]{margin-left:8px;width:18px;height:18px;transform:rotate(180deg)}.attachment-list-wrap[data-v-0702a552]{margin-top:12px;margin-left:42px}.attachment-list-wrap .n-upload-file-info__thumbnail[data-v-0702a552]{overflow:hidden}.detail-item{width:100%;padding:16px;box-sizing:border-box;background:#f7f9f9}.detail-item .nickname-wrap{font-size:14px}.detail-item .username-wrap{font-size:14px;opacity:.75}.detail-item .top-tag{transform:scale(.75)}.detail-item .options{opacity:.75}.detail-item .post-text{font-size:16px;text-align:justify;overflow:hidden;white-space:pre-wrap;word-break:break-all}.detail-item .opts-wrap{margin-top:20px}.detail-item .opts-wrap .opt-item{display:flex;align-items:center;opacity:.7}.detail-item .opts-wrap .opt-item .opt-item-icon{margin-right:10px}.detail-item .opts-wrap .opt-item.hover{cursor:pointer}.detail-item .n-thing .n-thing-avatar-header-wrapper{align-items:center}.detail-item .timestamp{opacity:.75;font-size:12px;margin-top:10px}.dark .detail-item{background:#18181c}.detail-wrap[data-v-41747510]{min-height:100px}
.reply-compose-wrap .reply-switch[data-v-3616e66c]{text-align:right;font-size:12px;margin:10px 0}.reply-compose-wrap .reply-switch .show[data-v-3616e66c]{color:#18a058;cursor:pointer}.reply-compose-wrap .reply-switch .hide[data-v-3616e66c]{opacity:.75;cursor:pointer}.reply-item[data-v-1e3df20d]{display:flex;flex-direction:column;font-size:12px;padding:8px;border-bottom:1px solid #f3f3f3}.reply-item .header-wrap[data-v-1e3df20d]{display:flex;align-items:center;justify-content:space-between}.reply-item .header-wrap .username[data-v-1e3df20d]{max-width:50%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.reply-item .header-wrap .username .reply-name[data-v-1e3df20d]{margin:0 3px;opacity:.75}.reply-item .header-wrap .timestamp[data-v-1e3df20d]{opacity:.75;text-align:right;display:flex;align-items:center;max-width:50%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.reply-item .base-wrap[data-v-1e3df20d]{display:flex}.reply-item .base-wrap .content[data-v-1e3df20d]{width:calc(100% - 40px);margin-top:4px;font-size:12px;text-align:justify;line-height:2}.reply-item .base-wrap .reply-switch[data-v-1e3df20d]{width:40px;text-align:right;font-size:12px;margin:10px 0 0}.reply-item .base-wrap .reply-switch .show[data-v-1e3df20d]{color:#18a058;cursor:pointer}.reply-item .base-wrap .reply-switch .hide[data-v-1e3df20d]{opacity:.75;cursor:pointer}.dark .reply-item[data-v-1e3df20d]{border-bottom:1px solid #262628}.comment-item[data-v-6b2cb186]{width:100%;padding:16px;box-sizing:border-box}.comment-item .nickname-wrap[data-v-6b2cb186]{font-size:14px}.comment-item .username-wrap[data-v-6b2cb186]{font-size:14px;opacity:.75}.comment-item .opt-wrap[data-v-6b2cb186]{display:flex;align-items:center}.comment-item .opt-wrap .timestamp[data-v-6b2cb186]{opacity:.75;font-size:12px}.comment-item .opt-wrap .del-btn[data-v-6b2cb186]{margin-left:4px}.comment-item .comment-text[data-v-6b2cb186]{display:block;text-align:justify;overflow:hidden;white-space:pre-wrap;word-break:break-all}.comment-item .opt-item[data-v-6b2cb186]{display:flex;align-items:center;opacity:.7}.comment-item .opt-item .opt-item-icon[data-v-6b2cb186]{margin-right:10px}.reply-wrap[data-v-6b2cb186]{margin-top:10px;border-radius:5px;background:#fafafc}.reply-wrap .reply-item[data-v-6b2cb186]:last-child{border-bottom:none}.dark .reply-wrap[data-v-6b2cb186]{background:#18181c}.compose-wrap[data-v-b1d2e9fe]{width:100%;padding:16px;box-sizing:border-box}.compose-wrap .compose-line[data-v-b1d2e9fe]{display:flex;flex-direction:row}.compose-wrap .compose-line .compose-user[data-v-b1d2e9fe]{width:42px;height:42px;display:flex;align-items:center}.compose-wrap .compose-line.compose-options[data-v-b1d2e9fe]{margin-top:6px;padding-left:42px;display:flex;justify-content:space-between}.compose-wrap .compose-line.compose-options .submit-wrap[data-v-b1d2e9fe]{display:flex;align-items:center}.compose-wrap .compose-line.compose-options .submit-wrap .cancel-btn[data-v-b1d2e9fe]{margin-right:8px}.compose-wrap .login-wrap[data-v-b1d2e9fe]{display:flex;justify-content:center;width:100%}.compose-wrap .login-wrap .login-banner[data-v-b1d2e9fe]{margin-bottom:12px;opacity:.8}.compose-wrap .login-wrap button[data-v-b1d2e9fe]{margin:0 4px}.attachment[data-v-b1d2e9fe]{display:flex;align-items:center}.attachment .text-statistic[data-v-b1d2e9fe]{margin-left:8px;width:18px;height:18px;transform:rotate(180deg)}.attachment-list-wrap[data-v-b1d2e9fe]{margin-top:12px;margin-left:42px}.attachment-list-wrap .n-upload-file-info__thumbnail[data-v-b1d2e9fe]{overflow:hidden}.detail-item{width:100%;padding:16px;box-sizing:border-box;background:#f7f9f9}.detail-item .nickname-wrap{font-size:14px}.detail-item .username-wrap{font-size:14px;opacity:.75}.detail-item .top-tag{transform:scale(.75)}.detail-item .options{opacity:.75}.detail-item .post-text{font-size:16px;text-align:justify;overflow:hidden;white-space:pre-wrap;word-break:break-all}.detail-item .opts-wrap{margin-top:20px}.detail-item .opts-wrap .opt-item{display:flex;align-items:center;opacity:.7}.detail-item .opts-wrap .opt-item .opt-item-icon{margin-right:10px}.detail-item .opts-wrap .opt-item.hover{cursor:pointer}.detail-item .n-thing .n-thing-avatar-header-wrapper{align-items:center}.detail-item .timestamp{opacity:.75;font-size:12px;margin-top:10px}.dark .detail-item{background:#18181c}.detail-wrap[data-v-41747510]{min-height:100px}

@ -0,0 +1 @@
import{_ as S}from"./post-item.11c28084.js";import{_ as U}from"./post-skeleton.38f0f247.js";import{_ as V}from"./main-nav.3167f221.js";import{ai as $,d as D,r as c,a2 as M,Y as o,a4 as e,a3 as _,a6 as h,a5 as r,a7 as d,aj as R,cc as j,W as t,Z as s,aa as f,ab as q,ac as F,$ as L,ae as T,c9 as W,ca as Y}from"./index.d4f5aad2.js";import{_ as Z}from"./List.a66e9ae7.js";import{_ as A}from"./Pagination.c13c2d34.js";import{a as G,_ as H}from"./Skeleton.e1c16fcb.js";import"./content.ed80294a.js";import"./formatTime.e07969bb.js";import"./Thing.d394adea.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=D({__name:"Profile",setup(oe){const a=L(),k=R(),l=c(!1),u=c([]),i=c(+k.query.p||1),p=c(20),m=c(0),v=()=>{l.value=!0,j({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 M(()=>{v()}),(n,_e)=>{const w=V,b=T,I=A,P=W,E=Y,x=U,B=G,C=S,z=H,N=Z;return t(),o("div",null,[e(w,{title:"\u4E3B\u9875"}),_(a).state.userInfo.id>0?(t(),h(N,{key:0,class:"main-content-wrap profile-wrap",bordered:""},{footer:r(()=>[m.value>1?(t(),o("div",ee,[e(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,[e(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)])]),e(E,{class:"profile-tabs-wrap",animated:""},{default:r(()=>[e(P,{name:"post",tab:"\u6CE1\u6CE1"})]),_:1}),l.value?(t(),o("div",te,[e(x,{num:p.value},null,8,["num"])])):(t(),o("div",ae,[u.value.length===0?(t(),o("div",se,[e(B,{size:"large",description:"\u6682\u65E0\u6570\u636E"})])):d("",!0),(t(!0),o(q,null,F(u.value,g=>(t(),h(z,{key:g.id},{default:r(()=>[e(C,{post:g},null,8,["post"])]),_:2},1024))),128))]))]),_:1})):d("",!0)])}}});var ge=$(ne,[["__scopeId","data-v-2fe5c266"]]);export{ge as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,34 @@
import{c as r,f as d,b as c,d as $,u as b,x as u,bB as y,j as E,y as S,A as w,h as i,ab as z}from"./index.d4f5aad2.js";var C=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;
`,[d("title",`
font-size: 16px;
font-weight: var(--n-title-font-weight);
transition: color .3s var(--n-bezier);
color: var(--n-title-text-color);
`)]),d("description",[c("&:not(:last-child)",`
margin-bottom: 4px;
`)]),d("content",[c("&:not(:first-child)",`
margin-top: 12px;
`)]),d("footer",[c("&:not(:first-child)",`
margin-top: 12px;
`)]),d("action",[c("&:not(:first-child)",`
margin-top: 12px;
`)])])]);const R=Object.assign(Object.assign({},u.props),{title:String,titleExtra:String,description:String,descriptionStyle:[String,Object],content:String,contentStyle:[String,Object],contentIndented:Boolean});var j=$({name:"Thing",props:R,setup(t,{slots:e}){const{mergedClsPrefixRef:h,inlineThemeDisabled:o,mergedRtlRef:f}=b(t),m=u("Thing","-thing",C,y,t,h),v=E("Thing",f,h),x=S(()=>{const{self:{titleTextColor:l,textColor:n,titleFontWeight:g,fontSize:s},common:{cubicBezierEaseInOut:_}}=m.value;return{"--n-bezier":_,"--n-font-size":s,"--n-text-color":n,"--n-title-font-weight":g,"--n-title-text-color":l}}),a=o?w("thing",void 0,x,t):void 0;return()=>{var l;const{value:n}=h,g=v?v.value:!1;return(l=a==null?void 0:a.onRender)===null||l===void 0||l.call(a),i("div",{class:[`${n}-thing`,a==null?void 0:a.themeClass,g&&`${n}-thing--rtl`],style:o?void 0:x.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`,style:t.descriptionStyle},e.description?e.description():t.description):null):null):i(z,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`,style:t.descriptionStyle},e.description?e.description():t.description):null),e.default||t.content?i("div",{class:`${n}-thing-main__content`,style:t.contentStyle},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{j as _};

@ -0,0 +1 @@
import{_ as k}from"./main-nav.3167f221.js";import{ai as w,d as x,r as s,a2 as B,Y as r,a4 as a,a5 as n,c8 as D,W as _,ab as q,ac as C,c9 as E,ca as N,am as V,ah as F,c7 as I,a6 as L,a9 as M,aa as m,Z as S,ae as U,ao as W}from"./index.d4f5aad2.js";import{_ as Y}from"./List.a66e9ae7.js";const Z={class:"tag-hot"},$=x({__name:"Topic",setup(j){const c=s([]),u=s("hot"),o=s(!1),l=()=>{o.value=!0,D({type:u.value,num:50}).then(e=>{c.value=e.topics,o.value=!1}).catch(e=>{o.value=!1})},i=e=>{u.value=e,l()};return B(()=>{l()}),(e,z)=>{const d=k,p=E,g=N,v=V("router-link"),f=U,h=W,y=F,T=I,b=Y;return _(),r("div",null,[a(d,{title:"\u8BDD\u9898"}),a(b,{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(T,{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",Z,"("+m(t.quote_num)+")",1)]),_:2},1024))),128))]),_:1})]),_:1},8,["show"])]),_:1})])}}});var J=w($,[["__scopeId","data-v-513fa4c6"]]);export{J as default};

@ -0,0 +1 @@
.tags-wrap[data-v-513fa4c6]{padding:20px}.tags-wrap .tag-item .tag-hot[data-v-513fa4c6]{margin-left:12px;font-size:12px;opacity:.75}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
.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-ca444ed2]{margin:10px 0}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
.auth-wrap[data-v-66895776]{margin-top:-30px}.rightbar-wrap[data-v-715681a1]{width:240px;position:fixed;left:calc(50% + var(--content-main) / 2 + 10px)}.rightbar-wrap .search-wrap[data-v-715681a1]{margin:12px 0}.rightbar-wrap .hot-tag-item[data-v-715681a1]{line-height:2;position:relative}.rightbar-wrap .hot-tag-item .hash-link[data-v-715681a1]{width:calc(100% - 60px);text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block}.rightbar-wrap .hot-tag-item .post-num[data-v-715681a1]{position:absolute;right:0;top:0;width:60px;text-align:right;line-height:2;opacity:.5}.rightbar-wrap .copyright-wrap[data-v-715681a1]{margin-top:10px}.rightbar-wrap .copyright-wrap .copyright[data-v-715681a1]{font-size:12px;opacity:.75}.rightbar-wrap .copyright-wrap .hash-link[data-v-715681a1]{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)}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
import{p as O,H as V,C as j,B as D,_ as E,a as F,b as L,c as M}from"./content.ed80294a.js";import{d as R,aj as S,al as I,$ as P,y as W,am as Y,W as o,Y as f,a4 as i,an as Z,a3 as t,a5 as n,ab as A,ac as G,a8 as v,Z as u,a9 as _,aa as p,a6 as r,a7 as c,ae as J,ao as K,af as Q,ah as U}from"./index.d4f5aad2.js";import{f as X}from"./formatTime.e07969bb.js";import{_ as tt}from"./Thing.d394adea.js";const et={class:"nickname-wrap"},st={class:"username-wrap"},at={class:"timestamp"},nt=["innerHTML"],ot={class:"opt-item"},it={class:"opt-item"},rt={class:"opt-item"},ut=R({__name:"post-item",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,$=tt;return o(),f("div",{class:"post-item",onClick:s[2]||(s[2]=g=>k(t(e).id))},[i($,{"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(t(e).user.nickname),1)]),_:1},8,["to"])]),u("span",st," @"+p(t(e).user.username),1),t(e).is_top?(o(),r(d,{key:0,class:"top-tag",type:"warning",size:"small",round:""},{default:n(()=>[_(" \u7F6E\u9876 ")]),_:1})):c("",!0),t(e).visibility==1?(o(),r(d,{key:1,class:"top-tag",type:"error",size:"small",round:""},{default:n(()=>[_(" \u79C1\u5BC6 ")]),_:1})):c("",!0),t(e).visibility==2?(o(),r(d,{key:2,class:"top-tag",type:"info",size:"small",round:""},{default:n(()=>[_(" \u597D\u53CB\u53EF\u89C1 ")]),_:1})):c("",!0)]),"header-extra":n(()=>[u("span",at,p(t(e).ip_loc?t(e).ip_loc+" \xB7 ":t(e).ip_loc)+" "+p(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"])):c("",!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"])):c("",!0),t(e).imgs.length>0?(o(),r(w,{key:2,imgs:t(e).imgs},null,8,["imgs"])):c("",!0),t(e).videos.length>0?(o(),r(T,{key:3,videos:t(e).videos},null,8,["videos"])):c("",!0),t(e).links.length>0?(o(),r(q,{key:4,links:t(e).links},null,8,["links"])):c("",!0)]),action:n(()=>[i(N,{justify:"space-between"},{default:n(()=>[u("div",ot,[i(h,{size:"18",class:"opt-item-icon"},{default:n(()=>[i(t(V))]),_:1}),_(" "+p(t(e).upvote_count),1)]),u("div",it,[i(h,{size:"18",class:"opt-item-icon"},{default:n(()=>[i(t(j))]),_:1}),_(" "+p(t(e).comment_count),1)]),u("div",rt,[i(h,{size:"18",class:"opt-item-icon"},{default:n(()=>[i(t(D))]),_:1}),_(" "+p(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,nt))),128))]),key:"0"}:void 0]),1024)])}}});export{ut as _};

@ -0,0 +1 @@
import{ai as r,d as c,W as s,Y as n,ac as l,Z as a,a4 as t,ab as p}from"./index.d4f5aad2.js";import{b as i}from"./Skeleton.e1c16fcb.js";const d={class:"user"},u={class:"content"},m=c({__name:"post-skeleton",props:{num:{default:1}},setup(o){return(v,k)=>{const e=i;return s(!0),n(p,null,l(new Array(o.num),_=>(s(),n("div",{class:"skeleton-item",key:_},[a("div",d,[t(e,{circle:"",size:"small"})]),a("div",u,[t(e,{text:"",repeat:3}),t(e,{text:"",style:{width:"60%"}})])]))),128)}}});var y=r(m,[["__scopeId","data-v-a6d56894"]]);export{y as _};

@ -6,7 +6,7 @@
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0" />
<title></title>
<script type="module" crossorigin src="/assets/index.428df323.js"></script>
<script type="module" crossorigin src="/assets/index.d4f5aad2.js"></script>
<link rel="stylesheet" href="/assets/index.cd3e5166.css">
</head>

@ -202,7 +202,7 @@ const loadSuggestionUsers = debounce((k) => {
})
.then((res) => {
let options: MentionOption[] = [];
res.map((i) => {
res.suggest.map((i) => {
options.push({
label: i,
value: i,

Loading…
Cancel
Save