Merge pull request #1 from rocboss/main

合并最新
pull/99/head
陈钦成 3 years ago committed by GitHub
commit 72e306d5d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

6
.gitignore vendored

@ -1,5 +1,7 @@
.idea
.vscode
__debug_bin
!*.example
dist/
config.yaml
*.log
paopao-api
paopao-ce*

@ -1,9 +1,9 @@
# build app
FROM golang AS build-env
ADD . /paopao-api
ADD . /paopao-ce
WORKDIR /paopao-api
WORKDIR /paopao-ce
RUN CGO_ENABLED=0 go build .
@ -14,14 +14,13 @@ ENV TZ=Asia/Shanghai
RUN apk update && apk add --no-cache ca-certificates && update-ca-certificates
COPY --from=build-env /paopao-api/paopao-api /usr/bin/paopao-api
COPY --from=build-env /paopao-api/comic.ttf /comic.ttf
COPY --from=build-env /paopao-api/qqwry.dat /qqwry.dat
COPY --from=build-env /paopao-api/configs /configs
COPY --from=build-env /paopao-ce/paopao-ce /usr/bin/paopao-ce
COPY --from=build-env /paopao-ce/assets/comic.ttf /assets/comic.ttf
COPY --from=build-env /paopao-ce/configs /configs
EXPOSE 8000
CMD ["paopao-api"]
CMD ["paopao-ce"]
# HEALTHCHECK
HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD ps -ef | grep paopao-api || exit 1
HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD ps -ef | grep paopao-ce || exit 1

@ -0,0 +1,33 @@
.PHONY: all build run clean fmt help
BUILD_VERSION := $(shell cat version)
BUILD_DATE := $(shell date +'%Y-%m-%d %H:%M:%S')
SHA_SHORT := $(shell git rev-parse --short HEAD)
TAGS = ""
all: fmt build
build:
@go mod download
@echo Build paopao-ce
bash build.sh paopao-ce
run:
@go run -tags '$(TAGS)' -ldflags "-X 'main.version=${BUILD_VERSION}' -X 'main.buildDate=${BUILD_DATE}' -X 'main.commitID=${SHA_SHORT}'" .
clean:
@go clean
@find ./dist -type f -exec rm -r {} +
@find ./tmp -type f -exec rm -r {} +
fmt:
@echo Formatting...
@go fmt ./global/...
@go fmt ./internal/...
@go fmt ./pkg/...
@go vet -composites=false ./global/...
@go vet -composites=false ./internal/...
@go vet -composites=false ./pkg/...
help:
@echo "make: make"
@echo "make run: start api server"
@echo "make build: build executables"
@echo "make build: build executables"
@echo "make run TAGS='embed': start api server and serve embed web frontend"
@echo "make build TAGS='embed': build executables with embed web frontend"
.EXPORT_ALL_VARIABLES:
GO111MODULE = on

@ -1,6 +1,5 @@
<div id="top"></div>
<!-- PROJECT SHIELDS -->
[![Go Report Card][goreport-shield]][goreport-url]
[![Forks][forks-shield]][forks-url]
@ -28,22 +27,22 @@
</p>
</div>
---
## 1. 截图预览
## 预览
Web端
[![明色主题][product-light-screenshot]](https://www.paopao.info)
[![暗色主题][product-dark-screenshot]](https://www.paopao.info)
更多演示请前往[官网](https://www.paopao.info)体验(谢绝灌水)
更多演示请前往[官网](https://www.paopao.info)体验(谢绝灌水)
<p align="right">(<a href="#top">back to top</a>)</p>
桌面端:
![](.github/desktop-tauri.jpeg)
<!-- GETTING STARTED -->
## 2. 快速开始
<p align="right">(<a href="#top">back to top</a>)</p>
### 2.1 技术栈
## 🛠 技术栈
PaoPao主要由以下优秀的开源项目/工具构建
@ -54,61 +53,116 @@ PaoPao主要由以下优秀的开源项目/工具构建
* [Vue.js](https://vuejs.org/)
* [Vite.js](https://vitejs.dev/)
<!-- GETTING STARTED -->
## 🏗 快速开始
### 2.2 环境要求
### 环境要求
- Go (1.17+)
- Node.js (14+)
- MySQL (5.7+)
- Redis
- Zinc
* Go (1.17+)
* Node.js (14+)
* MySQL (5.7+)
* Redis
* Zinc
\* Zinc是一款轻量级全文搜索引擎可以查阅 https://zincsearch.com/ 安装
\* Zinc是一款轻量级全文搜索引擎可以查阅 <https://zincsearch.com/> 安装
以上环境版本为PaoPao官方的开发版本仅供参考其他版本的环境未进行充分测试
<br />
### 安装说明
***宝塔安装***
我们为宝塔用户提供了超详细安装教程 [点此查看](https://www.rocs.me/archives/paopao_bt_install.html)
### 3. 安装说明
***普通安装***
克隆代码库
```sh
git clone https://github.com/rocboss/paopao-ce.git
```
#### 3.1 后端
#### 后端
1. 导入项目根目录下的 `paopao.sql` 文件至MySQL数据库
2. 拷贝项目根目录下 `config.yaml.sample` 文件至 `config.yaml`,按照注释完成配置编辑
3. 编译后端
3. 编译后端
编译api服务:
```sh
go mod download
go build -o paopao-api .
make build
```
4. 启动后端
编译api服务、内嵌web前端ui; 注意此步骤需要先编译web前端。
```sh
chmod +x paopao-api
./paopao-api
make build TAGS='embed'
```
编译后在`dist`目录可以找到对应可执行文件。
#### 3.2 前端
4. 启动后端
运行api服务:
```sh
make run
```
运行api服务、web前端ui服务:
```sh
make run TAGS='embed'
```
#### 前端
1. 进入前端目录 `web`,编辑 `.env` 文件中后端服务地址,下载依赖包
```sh
cd ./web
vim .env
yarn
```
2. 编译前端
```sh
yarn build
```
build完成后可以在dist目录获取编译产出配置nginx指向至该目录即可
#### 3.3 其他
建议后端服务使用 `supervisor` 守护进程并通过nginx反向代理后提供API给前端服务调用。
短信通道使用的juhe数据如果申请不下来可以考虑替换其他服务商。
代码结构比较简单喜欢的朋友欢迎给个Star、贡献PR。
#### 桌面端
1. 进入前端目录 `web`,编辑 `.env` 文件中后端服务地址,下载依赖包
```sh
cd ./web
vim .env
yarn
```
2. 编译前端
```sh
yarn build
```
3. 构建桌面端
```sh
yarn tauri build
```
桌面端是使用[Rust](https://www.rust-lang.org/) + [tauri](https://github.com/tauri-apps/tauri)编写
需要Rust编译环境具体安装指南请参考[https://www.rust-lang.org/tools/install](https://www.rust-lang.org/tools/install).
### 其他说明
建议后端服务使用 `supervisor` 守护进程,并通过 `nginx` 反向代理后提供API给前端服务调用。
短信通道使用的[聚合数据](https://www.juhe.cn/),如果申请不下来,可以考虑替换其他服务商。
代码结构比较简单,很方便扩展
## 👯‍♀️ 贡献
喜欢的朋友欢迎给个Star、贡献PR。
## License
Distributed under the MIT License. See `LICENSE` for more information.
<!-- MARKDOWN LINKS & IMAGES -->
[contributors-shield]: https://img.shields.io/github/contributors/rocboss/paopao-ce?style=flat
@ -125,4 +179,4 @@ PaoPao主要由以下优秀的开源项目/工具构建
[license-url]: https://github.com/rocboss/paopao-ce/blob/master/LICENSE.txt
[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=flat&logo=linkedin&colorB=555
[product-light-screenshot]: https://cdn.rocs.me/static/paopao-light.jpeg
[product-dark-screenshot]: https://cdn.rocs.me/static/paopao-dark.jpeg
[product-dark-screenshot]: https://cdn.rocs.me/static/paopao-dark.jpeg

@ -0,0 +1,35 @@
#!/usr/bin/env bash
# shellcheck disable=SC2155
set -e
DIST_PREFIX=${1}
DEBUG_MODE=${2}
TARGET_DIR="dist"
PLATFORMS="darwin/amd64 darwin/arm64 linux/amd64 windows/amd64"
rm -rf ${TARGET_DIR}
mkdir ${TARGET_DIR}
for pl in ${PLATFORMS}; do
export CGO_ENABLED=0
export GOOS=$(echo "${pl}" | cut -d'/' -f1)
export GOARCH=$(echo "${pl}" | cut -d'/' -f2)
export TARGET=${TARGET_DIR}/${DIST_PREFIX}_${GOOS}_${GOARCH}
if [ "${GOOS}" == "windows" ]; then
export TARGET=${TARGET_DIR}/${DIST_PREFIX}_${GOOS}_${GOARCH}.exe
fi
echo "build => ${TARGET}"
if [ "${DEBUG_MODE}" == "debug" ]; then
go build -trimpath -gcflags "all=-N -l" -o "${TARGET}" -tags "${TAGS}" \
-ldflags "-X 'main.version=${BUILD_VERSION}' \
-X 'main.buildDate=${BUILD_DATE}' \
-X 'main.commitID=${SHA_SHORT}'\
-w -s"
else
go build -trimpath -o "${TARGET}" -tags "${TAGS}" \
-ldflags "-X 'main.version=${BUILD_VERSION}' \
-X 'main.buildDate=${BUILD_DATE}' \
-X 'main.commitID=${SHA_SHORT}'\
-w -s"
fi
done

@ -10,6 +10,8 @@ App: # APP基础设置项
SmsJuheTplVal: "#code#=%d&#m#=%d"
AlipayAppID:
AlipayPrivateKey:
Runtime: # App运行时功能调节
DisablePhoneVerify: False # 禁止绑定手机号码时验证短信验证码为true时任意验证码都可以通过验证
Server: # 服务设置
RunMode: debug
HttpIp: 0.0.0.0

@ -10,6 +10,7 @@ import (
var (
ServerSetting *setting.ServerSettingS
AppSetting *setting.AppSettingS
RuntimeSetting *setting.RuntimeSettingS
DatabaseSetting *setting.DatabaseSettingS
RedisSetting *setting.RedisSettingS
SearchSetting *setting.SearchSettingS

@ -9,6 +9,7 @@ require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/disintegration/imaging v1.6.2
github.com/ethereum/go-ethereum v1.10.16
github.com/fatih/color v1.13.0
github.com/fbsobreira/gotron-sdk v0.0.0-20211102183839-58a64f4da5f4
github.com/gin-contrib/cors v1.3.1
github.com/gin-gonic/gin v1.7.7
@ -16,19 +17,18 @@ require (
github.com/go-redis/redis/v8 v8.11.4
github.com/go-resty/resty/v2 v2.7.0
github.com/gofrs/uuid v3.3.0+incompatible
github.com/golang/protobuf v1.5.2
github.com/google/go-cmp v0.5.7 // indirect
github.com/satori/go.uuid v1.2.0 // indirect
github.com/sirupsen/logrus v1.8.1
github.com/smartwalle/alipay/v3 v3.1.7
github.com/spf13/viper v1.10.1
github.com/ugorji/go v1.2.7 // indirect
github.com/yinheli/mahonia v0.0.0-20131226213531-0eef680515cc // indirect
github.com/yinheli/qqwry v0.0.0-20160229183603-f50680010f4a
github.com/yinheli/mahonia v0.0.0-20131226213531-0eef680515cc
golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect
google.golang.org/protobuf v1.27.1
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/resty.v1 v1.12.0
gorm.io/driver/mysql v1.3.2

@ -201,6 +201,7 @@ github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZ
github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fbsobreira/gotron-sdk v0.0.0-20211102183839-58a64f4da5f4 h1:zlN+of+l+or/Y6CYgpX99wwaTf4zN0myVj6YAXiE3xk=
@ -485,6 +486,7 @@ github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
@ -675,8 +677,6 @@ github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6Ut
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yinheli/mahonia v0.0.0-20131226213531-0eef680515cc h1:7VHQaaNwHymWbj8lAcXMYX1qopebSBHwYC3ceXLWONU=
github.com/yinheli/mahonia v0.0.0-20131226213531-0eef680515cc/go.mod h1:Pcc297eVCbkDBBVq8FbnI+qDUeIMrHy4Bo7nveAuCAs=
github.com/yinheli/qqwry v0.0.0-20160229183603-f50680010f4a h1:VUPXGL4N1B5xqomxI4vZn0momgleh0hcH0PE/oIOsAI=
github.com/yinheli/qqwry v0.0.0-20160229183603-f50680010f4a/go.mod h1:Zva9ErVtC2arl+9xtHwiXujgejX1S3VpOYExADJ9kio=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=

@ -8,8 +8,10 @@ import (
"github.com/go-redis/redis/v8"
"github.com/rocboss/paopao-ce/global"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/service"
"github.com/rocboss/paopao-ce/pkg/logger"
"github.com/rocboss/paopao-ce/pkg/setting"
"github.com/rocboss/paopao-ce/pkg/zinc"
)
func init() {
@ -25,6 +27,8 @@ func init() {
if err != nil {
log.Fatalf("init.setupDBEngine err: %v", err)
}
client := zinc.NewClient(global.SearchSetting)
service.Initialize(global.DBEngine, client)
}
func setupSetting() error {
@ -41,6 +45,10 @@ func setupSetting() error {
if err != nil {
return err
}
err = setting.ReadSection("Runtime", &global.RuntimeSetting)
if err != nil {
return err
}
err = setting.ReadSection("Log", &global.LoggerSetting)
if err != nil {
return err

@ -20,7 +20,7 @@ type Message struct {
SenderUserID int64 `json:"sender_user_id"`
ReceiverUserID int64 `json:"receiver_user_id"`
Type MessageT `json:"type"`
Breif string `json:"breif"`
Brief string `json:"brief"`
Content string `json:"content"`
PostID int64 `json:"post_id"`
CommentID int64 `json:"comment_id"`
@ -34,7 +34,7 @@ type MessageFormated struct {
SenderUser *UserFormated `json:"sender_user"`
ReceiverUserID int64 `json:"receiver_user_id"`
Type MessageT `json:"type"`
Breif string `json:"breif"`
Brief string `json:"brief"`
Content string `json:"content"`
PostID int64 `json:"post_id"`
Post *PostFormated `json:"post"`
@ -57,7 +57,7 @@ func (m *Message) Format() *MessageFormated {
SenderUser: &UserFormated{},
ReceiverUserID: m.ReceiverUserID,
Type: m.Type,
Breif: m.Breif,
Brief: m.Brief,
Content: m.Content,
PostID: m.PostID,
Post: &PostFormated{},

@ -53,9 +53,23 @@ func GetImageSize(img image.Rectangle) (int, int) {
return width, height
}
func fileCheck(uploadType string, size int64) error {
if uploadType != "public/video" &&
uploadType != "public/image" &&
uploadType != "public/avatar" &&
uploadType != "attachment" {
return errcode.InvalidParams
}
if size > 1024*1024*100 {
return errcode.FileInvalidSize.WithDetails("最大允许100MB")
}
return nil
}
func UploadAttachment(c *gin.Context) {
response := app.NewResponse(c)
svc := service.New(c)
uploadType := c.Request.FormValue("type")
file, fileHeader, err := c.Request.FormFile("file")
@ -66,16 +80,9 @@ func UploadAttachment(c *gin.Context) {
}
defer file.Close()
if uploadType != "public/video" &&
uploadType != "public/image" &&
uploadType != "public/avatar" &&
uploadType != "attachment" {
response.ToErrorResponse(errcode.InvalidParams)
return
}
if fileHeader.Size > 1024*1024*100 {
response.ToErrorResponse(errcode.FileInvalidSize.WithDetails("最大允许100MB"))
if err = fileCheck(uploadType, fileHeader.Size); err != nil {
cErr, _ := err.(*errcode.Error)
response.ToErrorResponse(cErr)
return
}
@ -129,24 +136,25 @@ func UploadAttachment(c *gin.Context) {
attachment.UserID = userID.(int64)
}
if uploadType == "public/image" || uploadType == "public/avatar" {
attachment.Type = model.ATTACHMENT_TYPE_IMAGE
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,
}
src, err := imaging.Decode(file)
attachment.Type = uploadAttachmentTypeMap[uploadType]
if attachment.Type == model.ATTACHMENT_TYPE_IMAGE {
var src image.Image
src, err = imaging.Decode(file)
if err == nil {
attachment.ImgWidth, attachment.ImgHeight = GetImageSize(src.Bounds())
}
}
if uploadType == "public/video" {
attachment.Type = model.ATTACHMENT_TYPE_VIDEO
}
if uploadType == "attachment" {
attachment.Type = model.ATTACHMENT_TYPE_OTHER
}
attachment, err = svc.CreateAttachment(attachment)
attachment, err = service.CreateAttachment(attachment)
if err != nil {
global.Logger.Errorf("svc.CreateAttachment err: %v", err)
global.Logger.Errorf("service.CreateAttachment err: %v", err)
response.ToErrorResponse(errcode.FileUploadFailed)
}
@ -155,21 +163,20 @@ func UploadAttachment(c *gin.Context) {
func DownloadAttachmentPrecheck(c *gin.Context) {
response := app.NewResponse(c)
svc := service.New(c)
contentID := convert.StrTo(c.Query("id")).MustInt64()
// 加载content
content, err := svc.GetPostContentByID(contentID)
content, err := service.GetPostContentByID(contentID)
if err != nil {
global.Logger.Errorf("svc.GetPostContentByID err: %v", err)
global.Logger.Errorf("service.GetPostContentByID err: %v", err)
response.ToErrorResponse(errcode.InvalidDownloadReq)
}
user, _ := c.Get("USER")
if content.Type == model.CONTENT_TYPE_CHARGE_ATTACHMENT {
// 加载post
post, err := svc.GetPost(content.PostID)
post, err := service.GetPost(content.PostID)
if err != nil {
global.Logger.Errorf("svc.GetPost err: %v", err)
global.Logger.Errorf("service.GetPost err: %v", err)
response.ToResponse(gin.H{
"paid": false,
})
@ -186,7 +193,7 @@ func DownloadAttachmentPrecheck(c *gin.Context) {
// 检测是否有购买记录
response.ToResponse(gin.H{
"paid": svc.CheckPostAttachmentIsPaid(post.ID, user.(*model.User).ID),
"paid": service.CheckPostAttachmentIsPaid(post.ID, user.(*model.User).ID),
})
return
}
@ -197,14 +204,13 @@ func DownloadAttachmentPrecheck(c *gin.Context) {
func DownloadAttachment(c *gin.Context) {
response := app.NewResponse(c)
svc := service.New(c)
contentID := convert.StrTo(c.Query("id")).MustInt64()
// 加载content
content, err := svc.GetPostContentByID(contentID)
content, err := service.GetPostContentByID(contentID)
if err != nil {
global.Logger.Errorf("svc.GetPostContentByID err: %v", err)
global.Logger.Errorf("service.GetPostContentByID err: %v", err)
response.ToErrorResponse(errcode.InvalidDownloadReq)
}
@ -213,9 +219,9 @@ func DownloadAttachment(c *gin.Context) {
user, _ := c.Get("USER")
// 加载post
post, err := svc.GetPost(content.PostID)
post, err := service.GetPost(content.PostID)
if err != nil {
global.Logger.Errorf("svc.GetPost err: %v", err)
global.Logger.Errorf("service.GetPost err: %v", err)
response.ToResponse(gin.H{
"paid": false,
})
@ -230,13 +236,13 @@ func DownloadAttachment(c *gin.Context) {
}
// 检测是否有购买记录
if svc.CheckPostAttachmentIsPaid(post.ID, user.(*model.User).ID) {
if service.CheckPostAttachmentIsPaid(post.ID, user.(*model.User).ID) {
paidFlag = true
}
if !paidFlag {
// 未购买,则尝试购买
err := svc.BuyPostAttachment(&model.Post{
err := service.BuyPostAttachment(&model.Post{
Model: &model.Model{
ID: post.ID,
},
@ -244,7 +250,7 @@ func DownloadAttachment(c *gin.Context) {
AttachmentPrice: post.AttachmentPrice,
}, user.(*model.User))
if err != nil {
global.Logger.Errorf("svc.BuyPostAttachment err: %v", err)
global.Logger.Errorf("service.BuyPostAttachment err: %v", err)
if err == errcode.InsuffientDownloadMoney {
response.ToErrorResponse(errcode.InsuffientDownloadMoney)

@ -11,15 +11,13 @@ import (
)
func GetPostComments(c *gin.Context) {
postID := convert.StrTo(c.Query("id")).MustInt64()
response := app.NewResponse(c)
svc := service.New(c)
contents, totalRows, err := svc.GetPostComments(postID, "id ASC", 0, 0)
contents, totalRows, err := service.GetPostComments(postID, "id ASC", 0, 0)
if err != nil {
global.Logger.Errorf("svc.GetPostComments err: %v\n", err)
global.Logger.Errorf("service.GetPostComments err: %v\n", err)
response.ToErrorResponse(errcode.GetCommentsFailed)
return
}
@ -38,14 +36,13 @@ func CreatePostComment(c *gin.Context) {
}
userID, _ := c.Get("UID")
svc := service.New(c)
comment, err := svc.CreatePostComment(userID.(int64), param)
comment, err := service.CreatePostComment(c, userID.(int64), param)
if err != nil {
if err == errcode.MaxCommentCount {
response.ToErrorResponse(errcode.MaxCommentCount)
} else {
global.Logger.Errorf("svc.CreatePostComment err: %v\n", err)
global.Logger.Errorf("service.CreatePostComment err: %v\n", err)
response.ToErrorResponse(errcode.CreateCommentFailed)
}
return
@ -64,11 +61,10 @@ func DeletePostComment(c *gin.Context) {
return
}
user, _ := c.Get("USER")
svc := service.New(c)
comment, err := svc.GetPostComment(param.ID)
comment, err := service.GetPostComment(param.ID)
if err != nil {
global.Logger.Errorf("svc.GetPostComment err: %v\n", err)
global.Logger.Errorf("service.GetPostComment err: %v\n", err)
response.ToErrorResponse(errcode.GetCommentFailed)
return
}
@ -79,9 +75,9 @@ func DeletePostComment(c *gin.Context) {
}
// 执行删除
err = svc.DeletePostComment(comment)
err = service.DeletePostComment(comment)
if err != nil {
global.Logger.Errorf("svc.DeletePostComment err: %v\n", err)
global.Logger.Errorf("service.DeletePostComment err: %v\n", err)
response.ToErrorResponse(errcode.DeleteCommentFailed)
return
}
@ -99,11 +95,10 @@ func CreatePostCommentReply(c *gin.Context) {
return
}
user, _ := c.Get("USER")
svc := service.New(c)
comment, err := svc.CreatePostCommentReply(param.CommentID, param.Content, user.(*model.User).ID, param.AtUserID)
comment, err := service.CreatePostCommentReply(c, param.CommentID, param.Content, user.(*model.User).ID, param.AtUserID)
if err != nil {
global.Logger.Errorf("svc.CreatePostCommentReply err: %v\n", err)
global.Logger.Errorf("service.CreatePostCommentReply err: %v\n", err)
response.ToErrorResponse(errcode.CreateReplyFailed)
return
}
@ -122,11 +117,10 @@ func DeletePostCommentReply(c *gin.Context) {
}
user, _ := c.Get("USER")
svc := service.New(c)
reply, err := svc.GetPostCommentReply(param.ID)
reply, err := service.GetPostCommentReply(param.ID)
if err != nil {
global.Logger.Errorf("svc.GetPostCommentReply err: %v\n", err)
global.Logger.Errorf("service.GetPostCommentReply err: %v\n", err)
response.ToErrorResponse(errcode.GetReplyFailed)
return
}
@ -137,9 +131,9 @@ func DeletePostCommentReply(c *gin.Context) {
}
// 执行删除
err = svc.DeletePostCommentReply(reply)
err = service.DeletePostCommentReply(reply)
if err != nil {
global.Logger.Errorf("svc.DeletePostCommentReply err: %v\n", err)
global.Logger.Errorf("service.DeletePostCommentReply err: %v\n", err)
response.ToErrorResponse(errcode.DeleteCommentFailed)
return
}

@ -30,12 +30,11 @@ func Version(c *gin.Context) {
func SyncSearchIndex(c *gin.Context) {
response := app.NewResponse(c)
svc := service.New(c)
user, _ := c.Get("USER")
if user.(*model.User).IsAdmin {
go svc.PushPostsToSearch()
go service.PushPostsToSearch(c)
}
response.ToResponse(nil)
@ -44,7 +43,7 @@ func SyncSearchIndex(c *gin.Context) {
func GetCaptcha(c *gin.Context) {
cap := captcha.New()
if err := cap.SetFont("comic.ttf"); err != nil {
if err := cap.SetFont("assets/comic.ttf"); err != nil {
panic(err.Error())
}
@ -77,7 +76,6 @@ func PostCaptcha(c *gin.Context) {
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
return
}
svc := service.New(c)
// 验证图片验证码
if res, err := global.Redis.Get(c.Request.Context(), "PaoPaoCaptcha:"+param.ImgCaptchaID).Result(); err != nil || res != param.ImgCaptcha {
@ -92,7 +90,7 @@ func PostCaptcha(c *gin.Context) {
return
}
err := svc.SendPhoneCaptcha(param.Phone)
err := service.SendPhoneCaptcha(c, param.Phone)
if err != nil {
global.Logger.Errorf("app.SendPhoneCaptcha errs: %v", errs)
response.ToErrorResponse(errcode.GetPhoneCaptchaError)

@ -16,9 +16,8 @@ func GetUnreadMsgCount(c *gin.Context) {
if u, exists := c.Get("USER"); exists {
user = u.(*model.User)
}
svc := service.New(c)
count, _ := svc.GetUnreadCount(user.ID)
count, _ := service.GetUnreadCount(user.ID)
response.ToResponse(gin.H{
"count": count,
@ -29,11 +28,10 @@ func GetMessages(c *gin.Context) {
response := app.NewResponse(c)
userID, _ := c.Get("UID")
svc := service.New(c)
messages, totalRows, err := svc.GetMessages(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c))
messages, totalRows, err := service.GetMessages(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c))
if err != nil {
global.Logger.Errorf("svc.GetMessages err: %v\n", err)
global.Logger.Errorf("service.GetMessages err: %v\n", err)
response.ToErrorResponse(errcode.GetMessagesFailed)
return
}
@ -52,10 +50,9 @@ func ReadMessage(c *gin.Context) {
}
userID, _ := c.Get("UID")
svc := service.New(c)
err := svc.ReadMessage(param.ID, userID.(int64))
err := service.ReadMessage(param.ID, userID.(int64))
if err != nil {
global.Logger.Errorf("svc.ReadMessage err: %v\n", err)
global.Logger.Errorf("service.ReadMessage err: %v\n", err)
response.ToErrorResponse(errcode.ReadMessageFailed)
return
}
@ -81,17 +78,16 @@ func SendUserWhisper(c *gin.Context) {
return
}
svc := service.New(c)
_, err := svc.CreateWhisper(&model.Message{
_, err := service.CreateWhisper(c, &model.Message{
SenderUserID: userID.(int64),
ReceiverUserID: param.UserID,
Type: model.MESSAGE_WHISPER,
Breif: "给你发送新私信了",
Brief: "给你发送新私信了",
Content: param.Content,
})
if err != nil {
global.Logger.Errorf("svc.CreateWhisper err: %v\n", err)
global.Logger.Errorf("service.CreateWhisper err: %v\n", err)
if err == errcode.TooManyWhisperNum {
response.ToErrorResponse(errcode.TooManyWhisperNum)

@ -22,10 +22,9 @@ func GetPostList(c *gin.Context) {
q.Type = "tag"
}
svc := service.New(c)
if q.Query == "" && q.Type == "search" {
// 直接读库
posts, err := svc.GetPostList(&service.PostListReq{
posts, err := service.GetPostList(&service.PostListReq{
Conditions: &model.ConditionsT{
"ORDER": "is_top DESC, latest_replied_on DESC",
},
@ -33,20 +32,20 @@ func GetPostList(c *gin.Context) {
Limit: app.GetPageSize(c),
})
if err != nil {
global.Logger.Errorf("svc.GetPostList err: %v\n", err)
global.Logger.Errorf("service.GetPostList err: %v\n", err)
response.ToErrorResponse(errcode.GetPostsFailed)
return
}
totalRows, _ := svc.GetPostCount(&model.ConditionsT{
totalRows, _ := service.GetPostCount(&model.ConditionsT{
"ORDER": "latest_replied_on DESC",
})
response.ToResponseList(posts, totalRows)
} else {
posts, totalRows, err := svc.GetPostListFromSearch(q, (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c))
posts, totalRows, err := service.GetPostListFromSearch(q, (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c))
if err != nil {
global.Logger.Errorf("svc.GetPostListFromSearch err: %v\n", err)
global.Logger.Errorf("service.GetPostListFromSearch err: %v\n", err)
response.ToErrorResponse(errcode.GetPostsFailed)
return
}
@ -58,11 +57,10 @@ func GetPost(c *gin.Context) {
postID := convert.StrTo(c.Query("id")).MustInt64()
response := app.NewResponse(c)
svc := service.New(c)
postFormated, err := svc.GetPost(postID)
postFormated, err := service.GetPost(postID)
if err != nil {
global.Logger.Errorf("svc.GetPost err: %v\n", err)
global.Logger.Errorf("service.GetPost err: %v\n", err)
response.ToErrorResponse(errcode.GetPostFailed)
return
}
@ -81,11 +79,10 @@ func CreatePost(c *gin.Context) {
}
userID, _ := c.Get("UID")
svc := service.New(c)
post, err := svc.CreatePost(userID.(int64), param)
post, err := service.CreatePost(c, userID.(int64), param)
if err != nil {
global.Logger.Errorf("svc.CreatePost err: %v\n", err)
global.Logger.Errorf("service.CreatePost err: %v\n", err)
response.ToErrorResponse(errcode.CreatePostFailed)
return
}
@ -104,12 +101,11 @@ func DeletePost(c *gin.Context) {
}
user, _ := c.Get("USER")
svc := service.New(c)
// 获取Post
postFormated, err := svc.GetPost(param.ID)
postFormated, err := service.GetPost(param.ID)
if err != nil {
global.Logger.Errorf("svc.GetPost err: %v\n", err)
global.Logger.Errorf("service.GetPost err: %v\n", err)
response.ToErrorResponse(errcode.GetPostFailed)
return
}
@ -119,9 +115,9 @@ func DeletePost(c *gin.Context) {
return
}
err = svc.DeletePost(param.ID)
err = service.DeletePost(param.ID)
if err != nil {
global.Logger.Errorf("svc.DeletePost err: %v\n", err)
global.Logger.Errorf("service.DeletePost err: %v\n", err)
response.ToErrorResponse(errcode.DeletePostFailed)
return
}
@ -133,10 +129,9 @@ func GetPostStar(c *gin.Context) {
postID := convert.StrTo(c.Query("id")).MustInt64()
response := app.NewResponse(c)
svc := service.New(c)
userID, _ := c.Get("UID")
_, err := svc.GetPostStar(postID, userID.(int64))
_, err := service.GetPostStar(postID, userID.(int64))
if err != nil {
response.ToResponse(gin.H{
"status": false,
@ -160,18 +155,17 @@ func PostStar(c *gin.Context) {
return
}
svc := service.New(c)
userID, _ := c.Get("UID")
status := false
star, err := svc.GetPostStar(param.ID, userID.(int64))
star, err := service.GetPostStar(param.ID, userID.(int64))
if err != nil {
// 创建Star
svc.CreatePostStar(param.ID, userID.(int64))
service.CreatePostStar(param.ID, userID.(int64))
status = true
} else {
// 取消Star
svc.DeletePostStar(star)
service.DeletePostStar(star)
}
response.ToResponse(gin.H{
@ -183,10 +177,9 @@ func GetPostCollection(c *gin.Context) {
postID := convert.StrTo(c.Query("id")).MustInt64()
response := app.NewResponse(c)
svc := service.New(c)
userID, _ := c.Get("UID")
_, err := svc.GetPostCollection(postID, userID.(int64))
_, err := service.GetPostCollection(postID, userID.(int64))
if err != nil {
response.ToResponse(gin.H{
"status": false,
@ -210,18 +203,17 @@ func PostCollection(c *gin.Context) {
return
}
svc := service.New(c)
userID, _ := c.Get("UID")
status := false
collection, err := svc.GetPostCollection(param.ID, userID.(int64))
collection, err := service.GetPostCollection(param.ID, userID.(int64))
if err != nil {
// 创建collection
svc.CreatePostCollection(param.ID, userID.(int64))
service.CreatePostCollection(param.ID, userID.(int64))
status = true
} else {
// 取消Star
svc.DeletePostCollection(collection)
service.DeletePostCollection(collection)
}
response.ToResponse(gin.H{
@ -240,12 +232,11 @@ func LockPost(c *gin.Context) {
}
user, _ := c.Get("USER")
svc := service.New(c)
// 获取Post
postFormated, err := svc.GetPost(param.ID)
postFormated, err := service.GetPost(param.ID)
if err != nil {
global.Logger.Errorf("svc.GetPost err: %v\n", err)
global.Logger.Errorf("service.GetPost err: %v\n", err)
response.ToErrorResponse(errcode.GetPostFailed)
return
}
@ -254,9 +245,9 @@ func LockPost(c *gin.Context) {
response.ToErrorResponse(errcode.NoPermission)
return
}
err = svc.LockPost(param.ID)
err = service.LockPost(param.ID)
if err != nil {
global.Logger.Errorf("svc.LockPost err: %v\n", err)
global.Logger.Errorf("service.LockPost err: %v\n", err)
response.ToErrorResponse(errcode.LockPostFailed)
return
}
@ -277,12 +268,11 @@ func StickPost(c *gin.Context) {
}
user, _ := c.Get("USER")
svc := service.New(c)
// 获取Post
postFormated, err := svc.GetPost(param.ID)
postFormated, err := service.GetPost(param.ID)
if err != nil {
global.Logger.Errorf("svc.GetPost err: %v\n", err)
global.Logger.Errorf("service.GetPost err: %v\n", err)
response.ToErrorResponse(errcode.GetPostFailed)
return
}
@ -291,9 +281,9 @@ func StickPost(c *gin.Context) {
response.ToErrorResponse(errcode.NoPermission)
return
}
err = svc.StickPost(param.ID)
err = service.StickPost(param.ID)
if err != nil {
global.Logger.Errorf("svc.StickPost err: %v\n", err)
global.Logger.Errorf("service.StickPost err: %v\n", err)
response.ToErrorResponse(errcode.LockPostFailed)
return
}
@ -313,11 +303,9 @@ func GetPostTags(c *gin.Context) {
return
}
svc := service.New(c)
tags, err := svc.GetPostTags(&param)
tags, err := service.GetPostTags(&param)
if err != nil {
global.Logger.Errorf("svc.GetPostTags err: %v\n", err)
global.Logger.Errorf("service.GetPostTags err: %v\n", err)
response.ToErrorResponse(errcode.GetPostTagsFailed)
return

@ -16,7 +16,7 @@ import (
"github.com/smartwalle/alipay/v3"
)
// 用户登录
// Login 用户登录
func Login(c *gin.Context) {
param := service.AuthRequest{}
response := app.NewResponse(c)
@ -27,10 +27,9 @@ func Login(c *gin.Context) {
return
}
svc := service.New(c)
user, err := svc.DoLogin(&param)
user, err := service.DoLogin(c, &param)
if err != nil {
global.Logger.Errorf("svc.DoLogin err: %v", err)
global.Logger.Errorf("service.DoLogin err: %v", err)
response.ToErrorResponse(err.(*errcode.Error))
return
}
@ -47,7 +46,7 @@ func Login(c *gin.Context) {
})
}
// 用户注册
// Register 用户注册
func Register(c *gin.Context) {
param := service.RegisterRequest{}
@ -59,31 +58,29 @@ func Register(c *gin.Context) {
return
}
svc := service.New(c)
// 用户名检查
err := svc.ValidUsername(param.Username)
err := service.ValidUsername(param.Username)
if err != nil {
global.Logger.Errorf("svc.Register err: %v", err)
global.Logger.Errorf("service.Register err: %v", err)
response.ToErrorResponse(err.(*errcode.Error))
return
}
// 密码检查
err = svc.CheckPassword(param.Password)
err = service.CheckPassword(param.Password)
if err != nil {
global.Logger.Errorf("svc.Register err: %v", err)
global.Logger.Errorf("service.Register err: %v", err)
response.ToErrorResponse(err.(*errcode.Error))
return
}
user, err := svc.Register(
user, err := service.Register(
param.Username,
param.Password,
)
if err != nil {
global.Logger.Errorf("svc.Register err: %v", err)
global.Logger.Errorf("service.Register err: %v", err)
response.ToErrorResponse(errcode.UserRegisterFailed)
return
}
@ -98,13 +95,12 @@ func Register(c *gin.Context) {
func GetUserInfo(c *gin.Context) {
param := service.AuthRequest{}
response := app.NewResponse(c)
svc := service.New(c)
if username, exists := c.Get("USERNAME"); exists {
param.Username = username.(string)
}
user, err := svc.GetUserInfo(&param)
user, err := service.GetUserInfo(&param)
if err != nil {
response.ToErrorResponse(errcode.UnauthorizedAuthNotExist)
@ -143,25 +139,23 @@ func ChangeUserPassword(c *gin.Context) {
user = u.(*model.User)
}
svc := service.New(c)
// 密码检查
err := svc.CheckPassword(param.Password)
err := service.CheckPassword(param.Password)
if err != nil {
global.Logger.Errorf("svc.Register err: %v", err)
global.Logger.Errorf("service.Register err: %v", err)
response.ToErrorResponse(err.(*errcode.Error))
return
}
// 旧密码校验
if !svc.ValidPassword(user.Password, param.OldPassword, user.Salt) {
if !service.ValidPassword(user.Password, param.OldPassword, user.Salt) {
response.ToErrorResponse(errcode.ErrorOldPassword)
return
}
// 更新入库
user.Password, user.Salt = svc.EncryptPasswordAndSalt(param.Password)
svc.UpdateUserInfo(user)
user.Password, user.Salt = service.EncryptPasswordAndSalt(param.Password)
service.UpdateUserInfo(user)
response.ToResponse(nil)
}
@ -181,7 +175,6 @@ func ChangeNickname(c *gin.Context) {
if u, exists := c.Get("USER"); exists {
user = u.(*model.User)
}
svc := service.New(c)
if utf8.RuneCountInString(param.Nickname) < 2 || utf8.RuneCountInString(param.Nickname) > 12 {
response.ToErrorResponse(errcode.NicknameLengthLimit)
@ -190,7 +183,7 @@ func ChangeNickname(c *gin.Context) {
// 执行绑定
user.Nickname = param.Nickname
svc.UpdateUserInfo(user)
service.UpdateUserInfo(user)
response.ToResponse(nil)
}
@ -210,7 +203,6 @@ func ChangeAvatar(c *gin.Context) {
if u, exists := c.Get("USER"); exists {
user = u.(*model.User)
}
svc := service.New(c)
if strings.Index(param.Avatar, "https://"+global.AliossSetting.AliossDomain) != 0 {
response.ToErrorResponse(errcode.InvalidParams)
@ -219,7 +211,7 @@ func ChangeAvatar(c *gin.Context) {
// 执行绑定
user.Avatar = param.Avatar
svc.UpdateUserInfo(user)
service.UpdateUserInfo(user)
response.ToResponse(nil)
}
@ -239,25 +231,25 @@ func BindUserPhone(c *gin.Context) {
if u, exists := c.Get("USER"); exists {
user = u.(*model.User)
}
svc := service.New(c)
// 手机重复性检查
if svc.CheckPhoneExist(user.ID, param.Phone) {
if service.CheckPhoneExist(user.ID, param.Phone) {
response.ToErrorResponse(errcode.ExistedUserPhone)
return
}
// 验证短信验证码
err := svc.CheckPhoneCaptcha(param.Phone, param.Captcha)
if err != nil {
global.Logger.Errorf("svc.CheckPhoneCaptcha err: %v\n", err)
response.ToErrorResponse(err)
return
if !global.RuntimeSetting.DisablePhoneVerify {
if err := service.CheckPhoneCaptcha(param.Phone, param.Captcha); err != nil {
global.Logger.Errorf("service.CheckPhoneCaptcha err: %v\n", err)
response.ToErrorResponse(err)
return
}
}
// 执行绑定
user.Phone = param.Phone
svc.UpdateUserInfo(user)
service.UpdateUserInfo(user)
response.ToResponse(nil)
}
@ -266,10 +258,9 @@ func GetUserProfile(c *gin.Context) {
response := app.NewResponse(c)
username := c.Query("username")
svc := service.New(c)
user, err := svc.GetUserByUsername(username)
user, err := service.GetUserByUsername(username)
if err != nil {
global.Logger.Errorf("svc.GetUserByUsername err: %v\n", err)
global.Logger.Errorf("service.GetUserByUsername err: %v\n", err)
response.ToErrorResponse(errcode.NoExistUsername)
return
}
@ -288,10 +279,9 @@ func GetUserPosts(c *gin.Context) {
response := app.NewResponse(c)
username := c.Query("username")
svc := service.New(c)
user, err := svc.GetUserByUsername(username)
user, err := service.GetUserByUsername(username)
if err != nil {
global.Logger.Errorf("svc.GetUserByUsername err: %v\n", err)
global.Logger.Errorf("service.GetUserByUsername err: %v\n", err)
response.ToErrorResponse(errcode.NoExistUsername)
return
}
@ -301,17 +291,17 @@ func GetUserPosts(c *gin.Context) {
"ORDER": "latest_replied_on DESC",
}
posts, err := svc.GetPostList(&service.PostListReq{
posts, err := service.GetPostList(&service.PostListReq{
Conditions: conditions,
Offset: (app.GetPage(c) - 1) * app.GetPageSize(c),
Limit: app.GetPageSize(c),
})
if err != nil {
global.Logger.Errorf("svc.GetPostList err: %v\n", err)
global.Logger.Errorf("service.GetPostList err: %v\n", err)
response.ToErrorResponse(errcode.GetPostsFailed)
return
}
totalRows, _ := svc.GetPostCount(conditions)
totalRows, _ := service.GetPostCount(conditions)
response.ToResponseList(posts, totalRows)
}
@ -320,11 +310,10 @@ func GetUserCollections(c *gin.Context) {
response := app.NewResponse(c)
userID, _ := c.Get("UID")
svc := service.New(c)
posts, totalRows, err := svc.GetUserCollections(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c))
posts, totalRows, err := service.GetUserCollections(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c))
if err != nil {
global.Logger.Errorf("svc.GetUserCollections err: %v\n", err)
global.Logger.Errorf("service.GetUserCollections err: %v\n", err)
response.ToErrorResponse(errcode.GetCollectionsFailed)
return
}
@ -336,10 +325,9 @@ func GetUserStars(c *gin.Context) {
response := app.NewResponse(c)
userID, _ := c.Get("UID")
svc := service.New(c)
posts, totalRows, err := svc.GetUserStars(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c))
posts, totalRows, err := service.GetUserStars(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c))
if err != nil {
global.Logger.Errorf("svc.GetUserStars err: %v\n", err)
global.Logger.Errorf("service.GetUserStars err: %v\n", err)
response.ToErrorResponse(errcode.GetCollectionsFailed)
return
}
@ -351,10 +339,9 @@ func GetSuggestUsers(c *gin.Context) {
keyword := c.Query("k")
response := app.NewResponse(c)
svc := service.New(c)
usernames, err := svc.GetSuggestUsers(keyword)
usernames, err := service.GetSuggestUsers(keyword)
if err != nil {
global.Logger.Errorf("svc.GetSuggestUsers err: %v\n", err)
global.Logger.Errorf("service.GetSuggestUsers err: %v\n", err)
response.ToErrorResponse(errcode.GetCollectionsFailed)
return
}
@ -366,10 +353,9 @@ func GetSuggestTags(c *gin.Context) {
keyword := c.Query("k")
response := app.NewResponse(c)
svc := service.New(c)
tags, err := svc.GetSuggestTags(keyword)
tags, err := service.GetSuggestTags(keyword)
if err != nil {
global.Logger.Errorf("svc.GetSuggestTags err: %v\n", err)
global.Logger.Errorf("service.GetSuggestTags err: %v\n", err)
response.ToErrorResponse(errcode.GetCollectionsFailed)
return
}
@ -389,10 +375,9 @@ func GetUserRechargeLink(c *gin.Context) {
// 下单
userID, _ := c.Get("UID")
svc := service.New(c)
recharge, err := svc.CreateRecharge(userID.(int64), param.Amount)
recharge, err := service.CreateRecharge(userID.(int64), param.Amount)
if err != nil {
global.Logger.Errorf("svc.CreateRecharge err: %v\n", err)
global.Logger.Errorf("service.CreateRecharge err: %v\n", err)
response.ToErrorResponse(errcode.RechargeReqFail)
return
@ -456,8 +441,7 @@ func GetUserRechargeResult(c *gin.Context) {
id := c.Query("id")
userID, _ := c.Get("UID")
svc := service.New(c)
recharge, err := svc.GetRechargeByID(convert.StrTo(id).MustInt64())
recharge, err := service.GetRechargeByID(convert.StrTo(id).MustInt64())
if err != nil {
response.ToErrorResponse(errcode.GetRechargeFailed)
return
@ -514,15 +498,14 @@ func AlipayNotify(c *gin.Context) {
return
}
svc := service.New(c)
id := c.Request.Form.Get("out_trade_no")
tradeNo := c.Request.Form.Get("trade_no")
tradeStatus := c.Request.Form.Get("trade_status")
if tradeStatus == "TRADE_SUCCESS" {
// 交易支付成功
err = svc.FinishRecharge(convert.StrTo(id).MustInt64(), tradeNo)
err = service.FinishRecharge(c, convert.StrTo(id).MustInt64(), tradeNo)
if err != nil {
global.Logger.Errorf("svc.FinishRecharge err: %v\n", err)
global.Logger.Errorf("service.FinishRecharge err: %v\n", err)
response.ToErrorResponse(errcode.RechargeNotifyError)
return
}
@ -534,11 +517,10 @@ func GetUserWalletBills(c *gin.Context) {
response := app.NewResponse(c)
userID, _ := c.Get("UID")
svc := service.New(c)
bills, totalRows, err := svc.GetUserWalletBills(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c))
bills, totalRows, err := service.GetUserWalletBills(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c))
if err != nil {
global.Logger.Errorf("svc.GetUserWalletBills err: %v\n", err)
global.Logger.Errorf("service.GetUserWalletBills err: %v\n", err)
response.ToErrorResponse(errcode.GetCollectionsFailed)
return
}

@ -10,16 +10,22 @@ import (
)
func NewRouter() *gin.Engine {
r := gin.New()
r.HandleMethodNotAllowed = true
r.Use(gin.Logger())
r.Use(gin.Recovery())
e := gin.New()
e.HandleMethodNotAllowed = true
e.Use(gin.Logger())
e.Use(gin.Recovery())
// 跨域配置
corsConfig := cors.DefaultConfig()
corsConfig.AllowAllOrigins = true
corsConfig.AddAllowHeaders("Authorization")
r.Use(cors.New(corsConfig))
e.Use(cors.New(corsConfig))
// 按需注册静态资源路由
registerStatick(e)
// v1 group api
r := e.Group("/v1")
// 获取version
r.GET("/", api.Version)
@ -163,18 +169,18 @@ func NewRouter() *gin.Engine {
}
// 默认404
r.NoRoute(func(c *gin.Context) {
e.NoRoute(func(c *gin.Context) {
c.JSON(http.StatusNotFound, gin.H{
"code": 404,
"msg": "Not Found",
})
})
// 默认405
r.NoMethod(func(c *gin.Context) {
e.NoMethod(func(c *gin.Context) {
c.JSON(http.StatusMethodNotAllowed, gin.H{
"code": 405,
"msg": "Method Not Allowed",
})
})
return r
return e
}

@ -0,0 +1,13 @@
//go:build !embed
// +build !embed
package routers
import (
"github.com/gin-gonic/gin"
)
// registerStatick stub function for register static asset route
func registerStatick(e *gin.Engine) {
// empty
}

@ -0,0 +1,27 @@
//go:build embed
// +build embed
package routers
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)
}
}

@ -2,6 +2,6 @@ package service
import "github.com/rocboss/paopao-ce/internal/model"
func (svc *Service) CreateAttachment(attachment *model.Attachment) (*model.Attachment, error) {
return svc.dao.CreateAttachment(attachment)
func CreateAttachment(attachment *model.Attachment) (*model.Attachment, error) {
return myDao.CreateAttachment(attachment)
}

@ -58,7 +58,7 @@ var defaultAvatars = []string{
"https://assets.paopao.info/public/avatar/default/abigail.png",
}
func (s *Service) GetRandomAvatar() string {
func GetRandomAvatar() string {
rand.Seed(time.Now().UnixMicro())
return defaultAvatars[rand.Intn(len(defaultAvatars))]
}

@ -4,6 +4,7 @@ import (
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/global"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/pkg/errcode"
@ -28,12 +29,12 @@ type ReplyDelReq struct {
ID int64 `json:"id" binding:"required"`
}
func (svc *Service) GetPostComments(postID int64, sort string, offset, limit int) ([]*model.CommentFormated, int64, error) {
func GetPostComments(postID int64, sort string, offset, limit int) ([]*model.CommentFormated, int64, error) {
conditions := &model.ConditionsT{
"post_id": postID,
"ORDER": sort,
}
comments, err := svc.dao.GetComments(conditions, offset, limit)
comments, err := myDao.GetComments(conditions, offset, limit)
if err != nil {
return nil, 0, err
@ -46,17 +47,17 @@ func (svc *Service) GetPostComments(postID int64, sort string, offset, limit int
commentIDs = append(commentIDs, comment.ID)
}
users, err := svc.dao.GetUsersByIDs(userIDs)
users, err := myDao.GetUsersByIDs(userIDs)
if err != nil {
return nil, 0, err
}
contents, err := svc.dao.GetCommentContentsByIDs(commentIDs)
contents, err := myDao.GetCommentContentsByIDs(commentIDs)
if err != nil {
return nil, 0, err
}
replies, err := svc.dao.GetCommentRepliesByID(commentIDs)
replies, err := myDao.GetCommentRepliesByID(commentIDs)
if err != nil {
return nil, 0, err
}
@ -84,14 +85,14 @@ func (svc *Service) GetPostComments(postID int64, sort string, offset, limit int
}
// 获取总量
totalRows, _ := svc.dao.GetCommentCount(conditions)
totalRows, _ := myDao.GetCommentCount(conditions)
return commentsFormated, totalRows, nil
}
func (svc *Service) CreatePostComment(userID int64, param CommentCreationReq) (*model.Comment, error) {
func CreatePostComment(ctx *gin.Context, userID int64, param CommentCreationReq) (*model.Comment, error) {
// 加载Post
post, err := svc.dao.GetPostByID(param.PostID)
post, err := myDao.GetPostByID(param.PostID)
if err != nil {
return nil, err
@ -100,14 +101,14 @@ func (svc *Service) CreatePostComment(userID int64, param CommentCreationReq) (*
if post.CommentCount >= global.AppSetting.MaxCommentCount {
return nil, errcode.MaxCommentCount
}
ip := svc.ctx.ClientIP()
ip := ctx.ClientIP()
comment := &model.Comment{
PostID: post.ID,
UserID: userID,
IP: ip,
IPLoc: util.GetIPLoc(ip),
}
comment, err = svc.dao.CreateComment(comment)
comment, err = myDao.CreateComment(comment)
if err != nil {
return nil, err
}
@ -127,41 +128,41 @@ func (svc *Service) CreatePostComment(userID int64, param CommentCreationReq) (*
Type: item.Type,
Sort: item.Sort,
}
svc.dao.CreateCommentContent(postContent)
myDao.CreateCommentContent(postContent)
}
// 更新Post回复数
post.CommentCount++
post.LatestRepliedOn = time.Now().Unix()
svc.dao.UpdatePost(post)
myDao.UpdatePost(post)
// 更新索引
go svc.PushPostToSearch(post)
go PushPostToSearch(post)
// 创建用户消息提醒
postMaster, err := svc.dao.GetUserByID(post.UserID)
postMaster, err := myDao.GetUserByID(post.UserID)
if err == nil && postMaster.ID != userID {
go svc.dao.CreateMessage(&model.Message{
go myDao.CreateMessage(&model.Message{
SenderUserID: userID,
ReceiverUserID: postMaster.ID,
Type: model.MESSAGE_COMMENT,
Breif: "在泡泡中评论了你",
Brief: "在泡泡中评论了你",
PostID: post.ID,
CommentID: comment.ID,
})
}
for _, u := range param.Users {
user, err := svc.dao.GetUserByUsername(u)
user, err := myDao.GetUserByUsername(u)
if err != nil || user.ID == userID || user.ID == postMaster.ID {
continue
}
// 创建消息提醒
go svc.dao.CreateMessage(&model.Message{
go myDao.CreateMessage(&model.Message{
SenderUserID: userID,
ReceiverUserID: user.ID,
Type: model.MESSAGE_COMMENT,
Breif: "在泡泡评论中@了你",
Brief: "在泡泡评论中@了你",
PostID: post.ID,
CommentID: comment.ID,
})
@ -170,37 +171,38 @@ func (svc *Service) CreatePostComment(userID int64, param CommentCreationReq) (*
return comment, nil
}
func (svc *Service) GetPostComment(id int64) (*model.Comment, error) {
return svc.dao.GetCommentByID(id)
func GetPostComment(id int64) (*model.Comment, error) {
return myDao.GetCommentByID(id)
}
func (svc *Service) DeletePostComment(comment *model.Comment) error {
func DeletePostComment(comment *model.Comment) error {
// 加载post
post, err := svc.dao.GetPostByID(comment.PostID)
post, err := myDao.GetPostByID(comment.PostID)
if err == nil {
// 更新post回复数
post.CommentCount--
svc.dao.UpdatePost(post)
myDao.UpdatePost(post)
}
return svc.dao.DeleteComment(comment)
return myDao.DeleteComment(comment)
}
func (svc *Service) CreatePostCommentReply(commentID int64, content string, userID, atUserID int64) (*model.CommentReply, error) {
func createPostPreHandler(commentID int64, userID, atUserID int64) (*model.Post, *model.Comment, int64,
error) {
// 加载Comment
comment, err := svc.dao.GetCommentByID(commentID)
comment, err := myDao.GetCommentByID(commentID)
if err != nil {
return nil, err
return nil, nil, atUserID, err
}
// 加载comment的post
post, err := svc.dao.GetPostByID(comment.PostID)
post, err := myDao.GetPostByID(comment.PostID)
if err != nil {
return nil, err
return nil, nil, atUserID, err
}
if post.CommentCount >= global.AppSetting.MaxCommentCount {
return nil, errcode.MaxCommentCount
return nil, nil, atUserID, errcode.MaxCommentCount
}
if userID == atUserID {
@ -209,14 +211,27 @@ func (svc *Service) CreatePostCommentReply(commentID int64, content string, user
if atUserID > 0 {
// 检测目前用户是否存在
users, _ := svc.dao.GetUsersByIDs([]int64{atUserID})
users, _ := myDao.GetUsersByIDs([]int64{atUserID})
if len(users) == 0 {
atUserID = 0
}
}
return post, comment, atUserID, nil
}
func CreatePostCommentReply(ctx *gin.Context, commentID int64, content string, userID, atUserID int64) (*model.CommentReply, error) {
var (
post *model.Post
comment *model.Comment
err error
)
if post, comment, atUserID, err = createPostPreHandler(commentID, userID, atUserID); err != nil {
return nil, err
}
// 创建评论
ip := svc.ctx.ClientIP()
ip := ctx.ClientIP()
reply := &model.CommentReply{
CommentID: commentID,
UserID: userID,
@ -226,7 +241,7 @@ func (svc *Service) CreatePostCommentReply(commentID int64, content string, user
IPLoc: util.GetIPLoc(ip),
}
reply, err = svc.dao.CreateCommentReply(reply)
reply, err = myDao.CreateCommentReply(reply)
if err != nil {
return nil, err
}
@ -234,45 +249,45 @@ func (svc *Service) CreatePostCommentReply(commentID int64, content string, user
// 更新Post回复数
post.CommentCount++
post.LatestRepliedOn = time.Now().Unix()
svc.dao.UpdatePost(post)
myDao.UpdatePost(post)
// 更新索引
go svc.PushPostToSearch(post)
go PushPostToSearch(post)
// 创建用户消息提醒
commentMaster, err := svc.dao.GetUserByID(comment.UserID)
commentMaster, err := myDao.GetUserByID(comment.UserID)
if err == nil && commentMaster.ID != userID {
go svc.dao.CreateMessage(&model.Message{
go myDao.CreateMessage(&model.Message{
SenderUserID: userID,
ReceiverUserID: commentMaster.ID,
Type: model.MESSAGE_REPLY,
Breif: "在泡泡评论下回复了你",
Brief: "在泡泡评论下回复了你",
PostID: post.ID,
CommentID: comment.ID,
ReplyID: reply.ID,
})
}
postMaster, err := svc.dao.GetUserByID(post.UserID)
postMaster, err := myDao.GetUserByID(post.UserID)
if err == nil && postMaster.ID != userID && commentMaster.ID != postMaster.ID {
go svc.dao.CreateMessage(&model.Message{
go myDao.CreateMessage(&model.Message{
SenderUserID: userID,
ReceiverUserID: postMaster.ID,
Type: model.MESSAGE_REPLY,
Breif: "在泡泡评论下发布了新回复",
Brief: "在泡泡评论下发布了新回复",
PostID: post.ID,
CommentID: comment.ID,
ReplyID: reply.ID,
})
}
if atUserID > 0 {
user, err := svc.dao.GetUserByID(atUserID)
user, err := myDao.GetUserByID(atUserID)
if err == nil && user.ID != userID && commentMaster.ID != user.ID && postMaster.ID != user.ID {
// 创建消息提醒
go svc.dao.CreateMessage(&model.Message{
go myDao.CreateMessage(&model.Message{
SenderUserID: userID,
ReceiverUserID: user.ID,
Type: model.MESSAGE_REPLY,
Breif: "在泡泡评论的回复中@了你",
Brief: "在泡泡评论的回复中@了你",
PostID: post.ID,
CommentID: comment.ID,
ReplyID: reply.ID,
@ -283,24 +298,24 @@ func (svc *Service) CreatePostCommentReply(commentID int64, content string, user
return reply, nil
}
func (svc *Service) GetPostCommentReply(id int64) (*model.CommentReply, error) {
return svc.dao.GetCommentReplyByID(id)
func GetPostCommentReply(id int64) (*model.CommentReply, error) {
return myDao.GetCommentReplyByID(id)
}
func (svc *Service) DeletePostCommentReply(reply *model.CommentReply) error {
err := svc.dao.DeleteCommentReply(reply)
func DeletePostCommentReply(reply *model.CommentReply) error {
err := myDao.DeleteCommentReply(reply)
if err != nil {
return err
}
// 加载Comment
comment, err := svc.dao.GetCommentByID(reply.CommentID)
comment, err := myDao.GetCommentByID(reply.CommentID)
if err != nil {
return err
}
// 加载comment的post
post, err := svc.dao.GetPostByID(comment.PostID)
post, err := myDao.GetPostByID(comment.PostID)
if err != nil {
return err
}
@ -308,10 +323,10 @@ func (svc *Service) DeletePostCommentReply(reply *model.CommentReply) error {
// 更新Post回复数
post.CommentCount--
post.LatestRepliedOn = time.Now().Unix()
svc.dao.UpdatePost(post)
myDao.UpdatePost(post)
// 更新索引
go svc.PushPostToSearch(post)
go PushPostToSearch(post)
return nil
}

@ -4,13 +4,14 @@ import (
"fmt"
"time"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/global"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/pkg/convert"
"github.com/rocboss/paopao-ce/pkg/errcode"
)
// 当日单用户私信总数限制TODO 配置化、积分兑换等)
// MAX_WHISPER_NUM_DAILY 当日单用户私信总数限制TODO 配置化、积分兑换等)
const MAX_WHISPER_NUM_DAILY = 20
type ReadMessageReq struct {
@ -21,37 +22,37 @@ type WhisperReq struct {
Content string `json:"content" binding:"required"`
}
// 创建私信
func (svc *Service) CreateWhisper(msg *model.Message) (*model.Message, error) {
// CreateWhisper 创建私信
func CreateWhisper(c *gin.Context, msg *model.Message) (*model.Message, error) {
whisperKey := fmt.Sprintf("WhisperTimes:%d", msg.SenderUserID)
// 今日频次限制
if res, _ := global.Redis.Get(svc.ctx, whisperKey).Result(); convert.StrTo(res).MustInt() >= MAX_WHISPER_NUM_DAILY {
if res, _ := global.Redis.Get(c, whisperKey).Result(); convert.StrTo(res).MustInt() >= MAX_WHISPER_NUM_DAILY {
return nil, errcode.TooManyWhisperNum
}
// 创建私信
msg, err := svc.dao.CreateMessage(msg)
msg, err := myDao.CreateMessage(msg)
if err != nil {
return nil, err
}
// 写入当日(自然日)计数缓存
global.Redis.Incr(svc.ctx, whisperKey).Result()
global.Redis.Incr(c, whisperKey).Result()
currentTime := time.Now()
endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, currentTime.Location())
global.Redis.Expire(svc.ctx, whisperKey, endTime.Sub(currentTime))
global.Redis.Expire(c, whisperKey, endTime.Sub(currentTime))
return msg, err
}
func (svc *Service) GetUnreadCount(userID int64) (int64, error) {
return svc.dao.GetUnreadCount(userID)
func GetUnreadCount(userID int64) (int64, error) {
return myDao.GetUnreadCount(userID)
}
func (svc *Service) ReadMessage(id, userID int64) error {
func ReadMessage(id, userID int64) error {
// 获取message
message, err := svc.dao.GetMessageByID(id)
message, err := myDao.GetMessageByID(id)
if err != nil {
return err
}
@ -61,20 +62,20 @@ func (svc *Service) ReadMessage(id, userID int64) error {
}
// 已读消息
return svc.dao.ReadMessage(message)
return myDao.ReadMessage(message)
}
func (svc *Service) GetMessages(userID int64, offset, limit int) ([]*model.MessageFormated, int64, error) {
func GetMessages(userID int64, offset, limit int) ([]*model.MessageFormated, int64, error) {
conditions := &model.ConditionsT{
"receiver_user_id": userID,
"ORDER": "id DESC",
}
messages, err := svc.dao.GetMessages(conditions, offset, limit)
messages, err := myDao.GetMessages(conditions, offset, limit)
for _, mf := range messages {
if mf.SenderUserID > 0 {
user, err := svc.dao.GetUserByID(mf.SenderUserID)
user, err := myDao.GetUserByID(mf.SenderUserID)
if err == nil {
mf.SenderUser = user.Format()
}
@ -82,17 +83,17 @@ func (svc *Service) GetMessages(userID int64, offset, limit int) ([]*model.Messa
}
if mf.PostID > 0 {
post, err := svc.GetPost(mf.PostID)
post, err := GetPost(mf.PostID)
if err == nil {
mf.Post = post
if mf.CommentID > 0 {
comment, err := svc.GetPostComment(mf.CommentID)
comment, err := GetPostComment(mf.CommentID)
if err == nil {
mf.Comment = comment
if mf.ReplyID > 0 {
reply, err := svc.GetPostCommentReply(mf.ReplyID)
reply, err := GetPostCommentReply(mf.ReplyID)
if err == nil {
mf.Reply = reply
}
@ -108,7 +109,7 @@ func (svc *Service) GetMessages(userID int64, offset, limit int) ([]*model.Messa
}
// 获取总量
totalRows, _ := svc.dao.GetMessageCount(conditions)
totalRows, _ := myDao.GetMessageCount(conditions)
return messages, totalRows, nil
}

@ -7,6 +7,7 @@ import (
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/global"
"github.com/rocboss/paopao-ce/internal/dao"
"github.com/rocboss/paopao-ce/internal/model"
@ -39,26 +40,50 @@ type PostCreationReq struct {
type PostDelReq struct {
ID int64 `json:"id" binding:"required"`
}
type PostLockReq struct {
ID int64 `json:"id" binding:"required"`
}
type PostStickReq struct {
ID int64 `json:"id" binding:"required"`
}
type PostStarReq struct {
ID int64 `json:"id" binding:"required"`
}
type PostCollectionReq struct {
ID int64 `json:"id" binding:"required"`
}
type PostContentItem struct {
Content string `json:"content" binding:"required"`
Type model.PostContentT `json:"type" binding:"required"`
Sort int64 `json:"sort" binding:"required"`
}
func (svc *Service) CreatePost(userID int64, param PostCreationReq) (*model.Post, error) {
ip := svc.ctx.ClientIP()
// 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 strings.Index(p.Content, "https://"+global.AliossSetting.AliossDomain) != 0 {
return fmt.Errorf("附件非本站资源")
}
}
// 检查链接是否合法
if p.Type == model.CONTENT_TYPE_LINK {
if strings.Index(p.Content, "http://") != 0 && strings.Index(p.Content, "https://") != 0 {
return fmt.Errorf("链接不合法")
}
}
return nil
}
func CreatePost(c *gin.Context, userID int64, param PostCreationReq) (*model.Post, error) {
ip := c.ClientIP()
post := &model.Post{
UserID: userID,
@ -67,7 +92,7 @@ func (svc *Service) CreatePost(userID int64, param PostCreationReq) (*model.Post
IPLoc: util.GetIPLoc(ip),
AttachmentPrice: param.AttachmentPrice,
}
post, err := svc.dao.CreatePost(post)
post, err := myDao.CreatePost(post)
if err != nil {
return nil, err
}
@ -78,22 +103,13 @@ func (svc *Service) CreatePost(userID int64, param PostCreationReq) (*model.Post
UserID: userID,
Tag: t,
}
svc.dao.CreateTag(tag)
myDao.CreateTag(tag)
}
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 strings.Index(item.Content, "https://"+global.AliossSetting.AliossDomain) != 0 {
continue
}
}
// 检查链接是否合法
if item.Type == model.CONTENT_TYPE_LINK {
if strings.Index(item.Content, "http://") != 0 && strings.Index(item.Content, "https://") != 0 {
continue
}
if err = item.Check(); err != nil {
// 属性非法
continue
}
if item.Type == model.CONTENT_TYPE_ATTACHMENT && param.AttachmentPrice > 0 {
@ -107,25 +123,25 @@ func (svc *Service) CreatePost(userID int64, param PostCreationReq) (*model.Post
Type: item.Type,
Sort: item.Sort,
}
svc.dao.CreatePostContent(postContent)
myDao.CreatePostContent(postContent)
}
// 推送Search
go svc.PushPostToSearch(post)
go PushPostToSearch(post)
// 创建用户消息提醒
for _, u := range param.Users {
user, err := svc.dao.GetUserByUsername(u)
user, err := myDao.GetUserByUsername(u)
if err != nil || user.ID == userID {
continue
}
// 创建消息提醒
go svc.dao.CreateMessage(&model.Message{
go myDao.CreateMessage(&model.Message{
SenderUserID: userID,
ReceiverUserID: user.ID,
Type: model.MESSAGE_POST,
Breif: "在新发布的泡泡动态中@了你",
Brief: "在新发布的泡泡动态中@了你",
PostID: post.ID,
})
}
@ -133,8 +149,8 @@ func (svc *Service) CreatePost(userID int64, param PostCreationReq) (*model.Post
return post, nil
}
func (svc *Service) DeletePost(id int64) error {
post, _ := svc.dao.GetPostByID(id)
func DeletePost(id int64) error {
post, _ := myDao.GetPostByID(id)
// tag删除
tags := strings.Split(post.Tags, ",")
@ -143,25 +159,25 @@ func (svc *Service) DeletePost(id int64) error {
tag := &model.Tag{
Tag: t,
}
svc.dao.DeleteTag(tag)
myDao.DeleteTag(tag)
}
err := svc.dao.DeletePost(post)
err := myDao.DeletePost(post)
if err != nil {
return err
}
// 删除索引
go svc.DeleteSearchPost(post)
go DeleteSearchPost(post)
return nil
}
func (svc *Service) LockPost(id int64) error {
post, _ := svc.dao.GetPostByID(id)
func LockPost(id int64) error {
post, _ := myDao.GetPostByID(id)
err := svc.dao.LockPost(post)
err := myDao.LockPost(post)
if err != nil {
return err
@ -170,10 +186,10 @@ func (svc *Service) LockPost(id int64) error {
return nil
}
func (svc *Service) StickPost(id int64) error {
post, _ := svc.dao.GetPostByID(id)
func StickPost(id int64) error {
post, _ := myDao.GetPostByID(id)
err := svc.dao.StickPost(post)
err := myDao.StickPost(post)
if err != nil {
return err
@ -182,109 +198,109 @@ func (svc *Service) StickPost(id int64) error {
return nil
}
func (svc *Service) GetPostStar(postID, userID int64) (*model.PostStar, error) {
return svc.dao.GetUserPostStar(postID, userID)
func GetPostStar(postID, userID int64) (*model.PostStar, error) {
return myDao.GetUserPostStar(postID, userID)
}
func (svc *Service) CreatePostStar(postID, userID int64) (*model.PostStar, error) {
func CreatePostStar(postID, userID int64) (*model.PostStar, error) {
// 加载Post
post, err := svc.dao.GetPostByID(postID)
post, err := myDao.GetPostByID(postID)
if err != nil {
return nil, err
}
star, err := svc.dao.CreatePostStar(postID, userID)
star, err := myDao.CreatePostStar(postID, userID)
if err != nil {
return nil, err
}
// 更新Post点赞数
post.UpvoteCount++
svc.dao.UpdatePost(post)
myDao.UpdatePost(post)
// 更新索引
go svc.PushPostToSearch(post)
go PushPostToSearch(post)
return star, nil
}
func (svc *Service) DeletePostStar(star *model.PostStar) error {
err := svc.dao.DeletePostStar(star)
func DeletePostStar(star *model.PostStar) error {
err := myDao.DeletePostStar(star)
if err != nil {
return err
}
// 加载Post
post, err := svc.dao.GetPostByID(star.PostID)
post, err := myDao.GetPostByID(star.PostID)
if err != nil {
return err
}
// 更新Post点赞数
post.UpvoteCount--
svc.dao.UpdatePost(post)
myDao.UpdatePost(post)
// 更新索引
go svc.PushPostToSearch(post)
go PushPostToSearch(post)
return nil
}
func (svc *Service) GetPostCollection(postID, userID int64) (*model.PostCollection, error) {
return svc.dao.GetUserPostCollection(postID, userID)
func GetPostCollection(postID, userID int64) (*model.PostCollection, error) {
return myDao.GetUserPostCollection(postID, userID)
}
func (svc *Service) CreatePostCollection(postID, userID int64) (*model.PostCollection, error) {
func CreatePostCollection(postID, userID int64) (*model.PostCollection, error) {
// 加载Post
post, err := svc.dao.GetPostByID(postID)
post, err := myDao.GetPostByID(postID)
if err != nil {
return nil, err
}
collection, err := svc.dao.CreatePostCollection(postID, userID)
collection, err := myDao.CreatePostCollection(postID, userID)
if err != nil {
return nil, err
}
// 更新Post点赞数
post.CollectionCount++
svc.dao.UpdatePost(post)
myDao.UpdatePost(post)
// 更新索引
go svc.PushPostToSearch(post)
go PushPostToSearch(post)
return collection, nil
}
func (svc *Service) DeletePostCollection(collection *model.PostCollection) error {
err := svc.dao.DeletePostCollection(collection)
func DeletePostCollection(collection *model.PostCollection) error {
err := myDao.DeletePostCollection(collection)
if err != nil {
return err
}
// 加载Post
post, err := svc.dao.GetPostByID(collection.PostID)
post, err := myDao.GetPostByID(collection.PostID)
if err != nil {
return err
}
// 更新Post点赞数
post.CollectionCount--
svc.dao.UpdatePost(post)
myDao.UpdatePost(post)
// 更新索引
go svc.PushPostToSearch(post)
go PushPostToSearch(post)
return nil
}
func (svc *Service) GetPost(id int64) (*model.PostFormated, error) {
post, err := svc.dao.GetPostByID(id)
func GetPost(id int64) (*model.PostFormated, error) {
post, err := myDao.GetPostByID(id)
if err != nil {
return nil, err
}
postContents, err := svc.dao.GetPostContentsByIDs([]int64{post.ID})
postContents, err := myDao.GetPostContentsByIDs([]int64{post.ID})
if err != nil {
return nil, err
}
users, err := svc.dao.GetUsersByIDs([]int64{post.UserID})
users, err := myDao.GetUsersByIDs([]int64{post.UserID})
if err != nil {
return nil, err
}
@ -302,21 +318,21 @@ func (svc *Service) GetPost(id int64) (*model.PostFormated, error) {
return postFormated, nil
}
func (svc *Service) GetPostContentByID(id int64) (*model.PostContent, error) {
return svc.dao.GetPostContentByID(id)
func GetPostContentByID(id int64) (*model.PostContent, error) {
return myDao.GetPostContentByID(id)
}
func (svc *Service) GetPostList(req *PostListReq) ([]*model.PostFormated, error) {
posts, err := svc.dao.GetPosts(req.Conditions, req.Offset, req.Limit)
func GetPostList(req *PostListReq) ([]*model.PostFormated, error) {
posts, err := myDao.GetPosts(req.Conditions, req.Offset, req.Limit)
if err != nil {
return nil, err
}
return svc.FormatPosts(posts)
return FormatPosts(posts)
}
func (svc *Service) FormatPosts(posts []*model.Post) ([]*model.PostFormated, error) {
func FormatPosts(posts []*model.Post) ([]*model.PostFormated, error) {
postIds := []int64{}
userIds := []int64{}
for _, post := range posts {
@ -324,12 +340,12 @@ func (svc *Service) FormatPosts(posts []*model.Post) ([]*model.PostFormated, err
userIds = append(userIds, post.UserID)
}
postContents, err := svc.dao.GetPostContentsByIDs(postIds)
postContents, err := myDao.GetPostContentsByIDs(postIds)
if err != nil {
return nil, err
}
users, err := svc.dao.GetUsersByIDs(userIds)
users, err := myDao.GetUsersByIDs(userIds)
if err != nil {
return nil, err
}
@ -356,17 +372,17 @@ func (svc *Service) FormatPosts(posts []*model.Post) ([]*model.PostFormated, err
return postsFormated, nil
}
func (svc *Service) GetPostCount(conditions *model.ConditionsT) (int64, error) {
return svc.dao.GetPostCount(conditions)
func GetPostCount(conditions *model.ConditionsT) (int64, error) {
return myDao.GetPostCount(conditions)
}
func (svc *Service) GetPostListFromSearch(q *dao.QueryT, offset, limit int) ([]*model.PostFormated, int64, error) {
queryResult, err := svc.dao.QueryAll(q, global.SearchSetting.ZincIndex, offset, limit)
func GetPostListFromSearch(q *dao.QueryT, offset, limit int) ([]*model.PostFormated, int64, error) {
queryResult, err := myDao.QueryAll(q, global.SearchSetting.ZincIndex, offset, limit)
if err != nil {
return nil, 0, err
}
posts, err := svc.FormatZincPost(queryResult)
posts, err := FormatZincPost(queryResult)
if err != nil {
return nil, 0, err
}
@ -374,13 +390,13 @@ func (svc *Service) GetPostListFromSearch(q *dao.QueryT, offset, limit int) ([]*
return posts, queryResult.Hits.Total.Value, nil
}
func (svc *Service) GetPostListFromSearchByQuery(query string, offset, limit int) ([]*model.PostFormated, int64, error) {
queryResult, err := svc.dao.QuerySearch(global.SearchSetting.ZincIndex, query, offset, limit)
func GetPostListFromSearchByQuery(query string, offset, limit int) ([]*model.PostFormated, int64, error) {
queryResult, err := myDao.QuerySearch(global.SearchSetting.ZincIndex, query, offset, limit)
if err != nil {
return nil, 0, err
}
posts, err := svc.FormatZincPost(queryResult)
posts, err := FormatZincPost(queryResult)
if err != nil {
return nil, 0, err
}
@ -388,14 +404,14 @@ func (svc *Service) GetPostListFromSearchByQuery(query string, offset, limit int
return posts, queryResult.Hits.Total.Value, nil
}
func (svc *Service) PushPostToSearch(post *model.Post) {
func PushPostToSearch(post *model.Post) {
indexName := global.SearchSetting.ZincIndex
postFormated := post.Format()
postFormated.User = &model.UserFormated{
ID: post.UserID,
}
contents, _ := svc.dao.GetPostContentsByIDs([]int64{post.ID})
contents, _ := myDao.GetPostContentsByIDs([]int64{post.ID})
for _, content := range contents {
postFormated.Contents = append(postFormated.Contents, content.Format())
}
@ -436,31 +452,31 @@ func (svc *Service) PushPostToSearch(post *model.Post) {
"modified_on": post.ModifiedOn,
})
svc.dao.BulkPushDoc(data)
myDao.BulkPushDoc(data)
}
func (svc *Service) DeleteSearchPost(post *model.Post) error {
func DeleteSearchPost(post *model.Post) error {
indexName := global.SearchSetting.ZincIndex
return svc.dao.DelDoc(indexName, fmt.Sprintf("%d", post.ID))
return myDao.DelDoc(indexName, fmt.Sprintf("%d", post.ID))
}
func (svc *Service) PushPostsToSearch() {
if ok, _ := global.Redis.SetNX(svc.ctx, "JOB_PUSH_TO_SEARCH", 1, time.Hour).Result(); ok {
func PushPostsToSearch(c *gin.Context) {
if ok, _ := global.Redis.SetNX(c, "JOB_PUSH_TO_SEARCH", 1, time.Hour).Result(); ok {
splitNum := 1000
totalRows, _ := svc.GetPostCount(&model.ConditionsT{})
totalRows, _ := GetPostCount(&model.ConditionsT{})
pages := math.Ceil(float64(totalRows) / float64(splitNum))
nums := int(pages)
indexName := global.SearchSetting.ZincIndex
// 创建索引
svc.dao.CreateSearchIndex(indexName)
myDao.CreateSearchIndex(indexName)
for i := 0; i < nums; i++ {
data := []map[string]interface{}{}
posts, _ := svc.GetPostList(&PostListReq{
posts, _ := GetPostList(&PostListReq{
Conditions: &model.ConditionsT{},
Offset: i * splitNum,
Limit: splitNum,
@ -499,15 +515,15 @@ func (svc *Service) PushPostsToSearch() {
}
if len(data) > 0 {
svc.dao.BulkPushDoc(data)
myDao.BulkPushDoc(data)
}
}
global.Redis.Del(svc.ctx, "JOB_PUSH_TO_SEARCH")
global.Redis.Del(c, "JOB_PUSH_TO_SEARCH")
}
}
func (svc *Service) FormatZincPost(queryResult *zinc.QueryResultT) ([]*model.PostFormated, error) {
func FormatZincPost(queryResult *zinc.QueryResultT) ([]*model.PostFormated, error) {
posts := []*model.PostFormated{}
for _, hit := range queryResult.Hits.Hits {
item := &model.PostFormated{}
@ -525,12 +541,12 @@ func (svc *Service) FormatZincPost(queryResult *zinc.QueryResultT) ([]*model.Pos
postIds = append(postIds, post.ID)
userIds = append(userIds, post.UserID)
}
postContents, err := svc.dao.GetPostContentsByIDs(postIds)
postContents, err := myDao.GetPostContentsByIDs(postIds)
if err != nil {
return nil, err
}
users, err := svc.dao.GetUsersByIDs(userIds)
users, err := myDao.GetUsersByIDs(userIds)
if err != nil {
return nil, err
}
@ -555,7 +571,7 @@ func (svc *Service) FormatZincPost(queryResult *zinc.QueryResultT) ([]*model.Pos
return posts, nil
}
func (svc *Service) GetPostTags(param *PostTagsReq) ([]*model.TagFormated, error) {
func GetPostTags(param *PostTagsReq) ([]*model.TagFormated, error) {
num := param.Num
if num > global.AppSetting.MaxPageSize {
num = global.AppSetting.MaxPageSize
@ -575,7 +591,7 @@ func (svc *Service) GetPostTags(param *PostTagsReq) ([]*model.TagFormated, error
}
}
tags, err := svc.dao.GetTags(conditions, 0, num)
tags, err := myDao.GetTags(conditions, 0, num)
if err != nil {
return nil, err
}
@ -586,7 +602,7 @@ func (svc *Service) GetPostTags(param *PostTagsReq) ([]*model.TagFormated, error
userIds = append(userIds, tag.UserID)
}
users, _ := svc.dao.GetUsersByIDs(userIds)
users, _ := myDao.GetUsersByIDs(userIds)
tagsFormated := []*model.TagFormated{}
for _, tag := range tags {
@ -602,8 +618,8 @@ func (svc *Service) GetPostTags(param *PostTagsReq) ([]*model.TagFormated, error
return tagsFormated, nil
}
func (svc *Service) CheckPostAttachmentIsPaid(postID, userID int64) bool {
bill, err := svc.dao.GetPostAttatchmentBill(postID, userID)
func CheckPostAttachmentIsPaid(postID, userID int64) bool {
bill, err := myDao.GetPostAttatchmentBill(postID, userID)
return err == nil && bill.Model != nil && bill.ID > 0
}

@ -1,26 +1,15 @@
package service
import (
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/global"
"github.com/rocboss/paopao-ce/internal/dao"
"github.com/rocboss/paopao-ce/pkg/zinc"
"gorm.io/gorm"
)
type Service struct {
ctx *gin.Context
dao *dao.Dao
}
func New(ctx *gin.Context) Service {
svc := Service{ctx: ctx}
svc.dao = dao.New(global.DBEngine, &zinc.ZincClient{
ZincClientConfig: &zinc.ZincClientConfig{
ZincHost: global.SearchSetting.ZincHost,
ZincUser: global.SearchSetting.ZincUser,
ZincPassword: global.SearchSetting.ZincPassword,
},
})
var (
myDao *dao.Dao
)
return svc
func Initialize(engine *gorm.DB, client *zinc.ZincClient) {
myDao = dao.New(engine, client)
}

@ -8,7 +8,7 @@ import (
"github.com/rocboss/paopao-ce/pkg/util"
)
func (svc *Service) GetParamSign(param map[string]interface{}, secretKey string) string {
func GetParamSign(param map[string]interface{}, secretKey string) string {
signRaw := ""
rawStrs := []string{}

@ -7,6 +7,7 @@ import (
"time"
"unicode/utf8"
"github.com/gin-gonic/gin"
"github.com/gofrs/uuid"
"github.com/rocboss/paopao-ce/global"
"github.com/rocboss/paopao-ce/internal/model"
@ -32,6 +33,7 @@ type AuthRequest struct {
Username string `json:"username" form:"username" binding:"required"`
Password string `json:"password" form:"password" binding:"required"`
}
type RegisterRequest struct {
Username string `json:"username" form:"username" binding:"required"`
Password string `json:"password" form:"password" binding:"required"`
@ -41,9 +43,11 @@ type ChangePasswordReq struct {
Password string `json:"password" form:"password" binding:"required"`
OldPassword string `json:"old_password" form:"old_password" binding:"required"`
}
type ChangeNicknameReq struct {
Nickname string `json:"nickname" form:"nickname" binding:"required"`
}
type ChangeAvatarReq struct {
Avatar string `json:"avatar" form:"avatar" binding:"required"`
}
@ -51,36 +55,36 @@ type ChangeAvatarReq struct {
const LOGIN_ERR_KEY = "PaoPaoUserLoginErr"
const MAX_LOGIN_ERR_TIMES = 10
// 用户认证
func (svc *Service) DoLogin(param *AuthRequest) (*model.User, error) {
user, err := svc.dao.GetUserByUsername(param.Username)
// DoLogin 用户认证
func DoLogin(ctx *gin.Context, param *AuthRequest) (*model.User, error) {
user, err := myDao.GetUserByUsername(param.Username)
if err != nil {
return nil, errcode.UnauthorizedAuthNotExist
}
if user.Model != nil && user.ID > 0 {
if errTimes, err := global.Redis.Get(svc.ctx, fmt.Sprintf("%s:%d", LOGIN_ERR_KEY, user.ID)).Result(); err == nil {
if errTimes, err := global.Redis.Get(ctx, fmt.Sprintf("%s:%d", LOGIN_ERR_KEY, user.ID)).Result(); err == nil {
if convert.StrTo(errTimes).MustInt() >= MAX_LOGIN_ERR_TIMES {
return nil, errcode.TooManyLoginError
}
}
// 对比密码是否正确
if svc.ValidPassword(user.Password, param.Password, user.Salt) {
if ValidPassword(user.Password, param.Password, user.Salt) {
if user.Status == model.UserStatusClosed {
return nil, errcode.UserHasBeenBanned
}
// 清空登录计数
global.Redis.Del(svc.ctx, fmt.Sprintf("%s:%d", LOGIN_ERR_KEY, user.ID))
global.Redis.Del(ctx, fmt.Sprintf("%s:%d", LOGIN_ERR_KEY, user.ID))
return user, nil
}
// 登录错误计数
_, err = global.Redis.Incr(svc.ctx, fmt.Sprintf("%s:%d", LOGIN_ERR_KEY, user.ID)).Result()
_, err = global.Redis.Incr(ctx, fmt.Sprintf("%s:%d", LOGIN_ERR_KEY, user.ID)).Result()
if err == nil {
global.Redis.Expire(svc.ctx, fmt.Sprintf("%s:%d", LOGIN_ERR_KEY, user.ID), time.Hour).Result()
global.Redis.Expire(ctx, fmt.Sprintf("%s:%d", LOGIN_ERR_KEY, user.ID), time.Hour).Result()
}
return nil, errcode.UnauthorizedAuthFailed
@ -89,18 +93,18 @@ func (svc *Service) DoLogin(param *AuthRequest) (*model.User, error) {
return nil, errcode.UnauthorizedAuthNotExist
}
// 检查密码是否一致
func (svc *Service) ValidPassword(dbPassword, password, salt string) bool {
// ValidPassword 检查密码是否一致
func ValidPassword(dbPassword, password, salt string) bool {
return strings.Compare(dbPassword, util.EncodeMD5(util.EncodeMD5(password)+salt)) == 0
}
// 检测用户权限
func (svc *Service) CheckStatus(user *model.User) bool {
// CheckStatus 检测用户权限
func CheckStatus(user *model.User) bool {
return user.Status == model.UserStatusNormal
}
// 验证用户
func (svc *Service) ValidUsername(username string) error {
// ValidUsername 验证用户
func ValidUsername(username string) error {
// 检测用户是否合规
if utf8.RuneCountInString(username) < 3 || utf8.RuneCountInString(username) > 12 {
return errcode.UsernameLengthLimit
@ -111,7 +115,7 @@ func (svc *Service) ValidUsername(username string) error {
}
// 重复检查
user, _ := svc.dao.GetUserByUsername(username)
user, _ := myDao.GetUserByUsername(username)
if user.Model != nil && user.ID > 0 {
return errcode.UsernameHasExisted
@ -120,8 +124,8 @@ func (svc *Service) ValidUsername(username string) error {
return nil
}
// 密码检查
func (svc *Service) CheckPassword(password string) error {
// CheckPassword 密码检查
func CheckPassword(password string) error {
// 检测用户是否合规
if utf8.RuneCountInString(password) < 6 || utf8.RuneCountInString(password) > 16 {
return errcode.PasswordLengthLimit
@ -130,9 +134,9 @@ func (svc *Service) CheckPassword(password string) error {
return nil
}
// 验证手机验证码
func (svc *Service) CheckPhoneCaptcha(phone, captcha string) *errcode.Error {
c, err := svc.dao.GetLatestPhoneCaptcha(phone)
// CheckPhoneCaptcha 验证手机验证码
func CheckPhoneCaptcha(phone, captcha string) *errcode.Error {
c, err := myDao.GetLatestPhoneCaptcha(phone)
if err != nil {
return errcode.ErrorPhoneCaptcha
}
@ -150,14 +154,14 @@ func (svc *Service) CheckPhoneCaptcha(phone, captcha string) *errcode.Error {
}
// 更新检测次数
svc.dao.UsePhoneCaptcha(c)
myDao.UsePhoneCaptcha(c)
return nil
}
// 检测手机号是否存在
func (svc *Service) CheckPhoneExist(uid int64, phone string) bool {
u, err := svc.dao.GetUserByPhone(phone)
// CheckPhoneExist 检测手机号是否存在
func CheckPhoneExist(uid int64, phone string) bool {
u, err := myDao.GetUserByPhone(phone)
if err != nil {
return false
}
@ -173,28 +177,28 @@ func (svc *Service) CheckPhoneExist(uid int64, phone string) bool {
return true
}
// 密码加密&生成salt
func (svc *Service) EncryptPasswordAndSalt(password string) (string, string) {
// 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
}
// 用户注册
func (svc *Service) Register(username, password string) (*model.User, error) {
password, salt := svc.EncryptPasswordAndSalt(password)
// Register 用户注册
func Register(username, password string) (*model.User, error) {
password, salt := EncryptPasswordAndSalt(password)
user := &model.User{
Nickname: username,
Username: username,
Password: password,
Avatar: svc.GetRandomAvatar(),
Avatar: GetRandomAvatar(),
Salt: salt,
Status: model.UserStatusNormal,
}
user, err := svc.dao.CreateUser(user)
user, err := myDao.CreateUser(user)
if err != nil {
return nil, err
}
@ -202,9 +206,9 @@ func (svc *Service) Register(username, password string) (*model.User, error) {
return user, nil
}
// 获取用户信息
func (svc *Service) GetUserInfo(param *AuthRequest) (*model.User, error) {
user, err := svc.dao.GetUserByUsername(param.Username)
// GetUserInfo 获取用户信息
func GetUserInfo(param *AuthRequest) (*model.User, error) {
user, err := myDao.GetUserByUsername(param.Username)
if err != nil {
return nil, err
@ -217,8 +221,8 @@ func (svc *Service) GetUserInfo(param *AuthRequest) (*model.User, error) {
return nil, errcode.UnauthorizedAuthNotExist
}
func (svc *Service) GetUserByUsername(username string) (*model.User, error) {
user, err := svc.dao.GetUserByUsername(username)
func GetUserByUsername(username string) (*model.User, error) {
user, err := myDao.GetUserByUsername(username)
if err != nil {
return nil, err
@ -231,18 +235,18 @@ func (svc *Service) GetUserByUsername(username string) (*model.User, error) {
return nil, errcode.NoExistUsername
}
// 更新用户信息
func (svc *Service) UpdateUserInfo(user *model.User) error {
return svc.dao.UpdateUser(user)
// UpdateUserInfo 更新用户信息
func UpdateUserInfo(user *model.User) error {
return myDao.UpdateUser(user)
}
// 获取用户收藏列表
func (svc *Service) GetUserCollections(userID int64, offset, limit int) ([]*model.PostFormated, int64, error) {
collections, err := svc.dao.GetUserPostCollections(userID, offset, limit)
// GetUserCollections 获取用户收藏列表
func GetUserCollections(userID int64, offset, limit int) ([]*model.PostFormated, int64, error) {
collections, err := myDao.GetUserPostCollections(userID, offset, limit)
if err != nil {
return nil, 0, err
}
totalRows, err := svc.dao.GetUserPostCollectionCount(userID)
totalRows, err := myDao.GetUserPostCollectionCount(userID)
if err != nil {
return nil, 0, err
}
@ -252,7 +256,7 @@ func (svc *Service) GetUserCollections(userID int64, offset, limit int) ([]*mode
}
// 获取Posts
posts, err := svc.dao.GetPosts(&model.ConditionsT{
posts, err := myDao.GetPosts(&model.ConditionsT{
"id IN ?": postIDs,
"ORDER": "id DESC",
}, 0, 0)
@ -260,7 +264,7 @@ func (svc *Service) GetUserCollections(userID int64, offset, limit int) ([]*mode
return nil, 0, err
}
postsFormated, err := svc.FormatPosts(posts)
postsFormated, err := FormatPosts(posts)
if err != nil {
return nil, 0, err
}
@ -268,13 +272,13 @@ func (svc *Service) GetUserCollections(userID int64, offset, limit int) ([]*mode
return postsFormated, totalRows, nil
}
// 获取用户点赞列表
func (svc *Service) GetUserStars(userID int64, offset, limit int) ([]*model.PostFormated, int64, error) {
stars, err := svc.dao.GetUserPostStars(userID, offset, limit)
// GetUserStars 获取用户点赞列表
func GetUserStars(userID int64, offset, limit int) ([]*model.PostFormated, int64, error) {
stars, err := myDao.GetUserPostStars(userID, offset, limit)
if err != nil {
return nil, 0, err
}
totalRows, err := svc.dao.GetUserPostStarCount(userID)
totalRows, err := myDao.GetUserPostStarCount(userID)
if err != nil {
return nil, 0, err
}
@ -284,7 +288,7 @@ func (svc *Service) GetUserStars(userID int64, offset, limit int) ([]*model.Post
}
// 获取Posts
posts, err := svc.dao.GetPosts(&model.ConditionsT{
posts, err := myDao.GetPosts(&model.ConditionsT{
"id IN ?": postIDs,
"ORDER": "id DESC",
}, 0, 0)
@ -292,7 +296,7 @@ func (svc *Service) GetUserStars(userID int64, offset, limit int) ([]*model.Post
return nil, 0, err
}
postsFormated, err := svc.FormatPosts(posts)
postsFormated, err := FormatPosts(posts)
if err != nil {
return nil, 0, err
}
@ -300,13 +304,13 @@ func (svc *Service) GetUserStars(userID int64, offset, limit int) ([]*model.Post
return postsFormated, totalRows, nil
}
// 获取用户账单列表
func (svc *Service) GetUserWalletBills(userID int64, offset, limit int) ([]*model.WalletStatement, int64, error) {
bills, err := svc.dao.GetUserWalletBills(userID, offset, limit)
// GetUserWalletBills 获取用户账单列表
func GetUserWalletBills(userID int64, offset, limit int) ([]*model.WalletStatement, int64, error) {
bills, err := myDao.GetUserWalletBills(userID, offset, limit)
if err != nil {
return nil, 0, err
}
totalRows, err := svc.dao.GetUserWalletBillCount(userID)
totalRows, err := myDao.GetUserWalletBillCount(userID)
if err != nil {
return nil, 0, err
}
@ -314,28 +318,28 @@ func (svc *Service) GetUserWalletBills(userID int64, offset, limit int) ([]*mode
return bills, totalRows, nil
}
// 发送短信验证码
func (svc *Service) SendPhoneCaptcha(phone string) error {
// SendPhoneCaptcha 发送短信验证码
func SendPhoneCaptcha(ctx *gin.Context, phone string) error {
err := svc.dao.SendPhoneCaptcha(phone)
err := myDao.SendPhoneCaptcha(phone)
if err != nil {
return err
}
// 写入计数缓存
global.Redis.Incr(svc.ctx, "PaoPaoSmsCaptcha:"+phone).Result()
global.Redis.Incr(ctx, "PaoPaoSmsCaptcha:"+phone).Result()
currentTime := time.Now()
endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, currentTime.Location())
global.Redis.Expire(svc.ctx, "PaoPaoSmsCaptcha:"+phone, endTime.Sub(currentTime))
global.Redis.Expire(ctx, "PaoPaoSmsCaptcha:"+phone, endTime.Sub(currentTime))
return nil
}
// 根据关键词获取用户推荐
func (svc *Service) GetSuggestUsers(keyword string) ([]string, error) {
users, err := svc.dao.GetUsersByKeyword(keyword)
// GetSuggestUsers 根据关键词获取用户推荐
func GetSuggestUsers(keyword string) ([]string, error) {
users, err := myDao.GetUsersByKeyword(keyword)
if err != nil {
return nil, err
}
@ -348,9 +352,9 @@ func (svc *Service) GetSuggestUsers(keyword string) ([]string, error) {
return usernames, nil
}
// 根据关键词获取标签推荐
func (svc *Service) GetSuggestTags(keyword string) ([]string, error) {
tags, err := svc.dao.GetTagsByKeyword(keyword)
// GetSuggestTags 根据关键词获取标签推荐
func GetSuggestTags(keyword string) ([]string, error) {
tags, err := myDao.GetTagsByKeyword(keyword)
if err != nil {
return nil, err
}

@ -3,6 +3,7 @@ package service
import (
"time"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/global"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/pkg/errcode"
@ -12,17 +13,17 @@ type RechargeReq struct {
Amount int64 `json:"amount" form:"amount" binding:"required"`
}
func (svc *Service) GetRechargeByID(id int64) (*model.WalletRecharge, error) {
return svc.dao.GetRechargeByID(id)
func GetRechargeByID(id int64) (*model.WalletRecharge, error) {
return myDao.GetRechargeByID(id)
}
func (svc *Service) CreateRecharge(userID, amount int64) (*model.WalletRecharge, error) {
return svc.dao.CreateRecharge(userID, amount)
func CreateRecharge(userID, amount int64) (*model.WalletRecharge, error) {
return myDao.CreateRecharge(userID, amount)
}
func (svc *Service) FinishRecharge(id int64, tradeNo string) error {
if ok, _ := global.Redis.SetNX(svc.ctx, "PaoPaoRecharge:"+tradeNo, 1, time.Second*5).Result(); ok {
recharge, err := svc.dao.GetRechargeByID(id)
func FinishRecharge(ctx *gin.Context, id int64, tradeNo string) error {
if ok, _ := global.Redis.SetNX(ctx, "PaoPaoRecharge:"+tradeNo, 1, time.Second*5).Result(); ok {
recharge, err := myDao.GetRechargeByID(id)
if err != nil {
return err
}
@ -30,8 +31,8 @@ func (svc *Service) FinishRecharge(id int64, tradeNo string) error {
if recharge.TradeStatus != "TRADE_SUCCESS" {
// 标记为已付款
err := svc.dao.HandleRechargeSuccess(recharge, tradeNo)
defer global.Redis.Del(svc.ctx, "PaoPaoRecharge:"+tradeNo)
err := myDao.HandleRechargeSuccess(recharge, tradeNo)
defer global.Redis.Del(ctx, "PaoPaoRecharge:"+tradeNo)
if err != nil {
return err
@ -43,11 +44,11 @@ func (svc *Service) FinishRecharge(id int64, tradeNo string) error {
return nil
}
func (svc *Service) BuyPostAttachment(post *model.Post, user *model.User) error {
func BuyPostAttachment(post *model.Post, user *model.User) error {
if user.Balance < post.AttachmentPrice {
return errcode.InsuffientDownloadMoney
}
// 执行购买
return svc.dao.HandlePostAttachmentBought(post, user)
return myDao.HandlePostAttachmentBought(post, user)
}

@ -4,9 +4,15 @@ import (
"fmt"
"net/http"
"github.com/fatih/color"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/global"
"github.com/rocboss/paopao-ce/internal/routers"
"github.com/rocboss/paopao-ce/pkg/util"
)
var (
version, buildDate, commitID string
)
func main() {
@ -21,6 +27,9 @@ func main() {
MaxHeaderBytes: 1 << 20,
}
fmt.Printf("\x1b[36m%s\x1b[0m\n", "PaoPao service listen on http://"+global.ServerSetting.HttpIp+":"+global.ServerSetting.HttpPort)
util.PrintHelloBanner(fmt.Sprintf("paopao %s (build:%s %s)", version, commitID, buildDate))
fmt.Fprintf(color.Output, "PaoPao service listen on %s\n",
color.GreenString(fmt.Sprintf("http://%s:%s", global.ServerSetting.HttpIp, global.ServerSetting.HttpPort)),
)
s.ListenAndServe()
}

@ -111,7 +111,7 @@ CREATE TABLE `p_message` (
`sender_user_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '发送方用户ID',
`receiver_user_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '接收方用户ID',
`type` tinyint unsigned NOT NULL DEFAULT '1' COMMENT '通知类型1动态2评论3回复4私信99系统通知',
`breif` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '摘要说明',
`brief` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '摘要说明',
`content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '详细内容',
`post_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '动态ID',
`comment_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '评论ID',

@ -51,6 +51,10 @@ type AppSettingS struct {
AlipayPrivateKey string
}
type RuntimeSettingS struct {
DisablePhoneVerify bool
}
type SearchSettingS struct {
ZincHost string
ZincIndex string

@ -6,8 +6,8 @@ import (
"time"
"github.com/fbsobreira/gotron-sdk/pkg/proto/core"
"github.com/golang/protobuf/proto"
"github.com/rocboss/paopao-ce/pkg/crypto"
"google.golang.org/protobuf/proto"
)
// SignTransaction 签名交易

@ -0,0 +1,12 @@
package util
import "fmt"
func PrintHelloBanner(text string) {
fmt.Println(" ____ __ __ ____ __ __ ")
fmt.Println("( _ \\ / _\\ / \\( _ \\ / _\\ / \\ ")
fmt.Println(" ) __// \\( O )) __// \\( O )")
fmt.Println("(__) \\_/\\_/ \\__/(__) \\_/\\_/ \\__/ ")
fmt.Println(text)
}

@ -1,12 +1,8 @@
package util
import (
"github.com/yinheli/qqwry"
)
import "github.com/rocboss/paopao-ce/pkg/util/iploc"
func GetIPLoc(ip string) string {
q := qqwry.NewQQwry("qqwry.dat")
q.Find(ip)
return q.Country
country, _ := iploc.Find(ip)
return country
}

@ -0,0 +1,128 @@
package iploc
import (
_ "embed"
"encoding/binary"
"net"
"github.com/yinheli/mahonia"
)
// Note: This file is a modified version of https://github.com/yinheli/qqwry.
//go:embed qqwry.dat
var qqwry []byte
const (
cIndexLen = 7
cRedirectMode1 = 0x01
cRedirectMode2 = 0x02
)
// Find get country and city base ip
func Find(ip string) (string, string) {
offset := searchIndex(binary.BigEndian.Uint32(net.ParseIP(ip).To4()))
if offset <= 0 {
return "", ""
}
var country, area []byte
mode := readMode(offset + 4)
if mode == cRedirectMode1 {
countryOffset := readUInt24(offset + 5)
mode = readMode(countryOffset)
if mode == cRedirectMode2 {
c := readUInt24(countryOffset + 1)
country = readString(c)
countryOffset += 4
} else {
country = readString(countryOffset)
countryOffset += uint32(len(country) + 1)
}
area = readArea(countryOffset)
} else if mode == cRedirectMode2 {
countryOffset := readUInt24(offset + 5)
country = readString(countryOffset)
area = readArea(offset + 8)
} else {
country = readString(offset + 4)
area = readArea(offset + uint32(5+len(country)))
}
enc := mahonia.NewDecoder("gbk")
Country := enc.ConvertString(string(country))
City := enc.ConvertString(string(area))
return Country, City
}
func readMode(offset uint32) byte {
return qqwry[offset]
}
func readArea(offset uint32) []byte {
mode := readMode(offset)
if mode == cRedirectMode1 || mode == cRedirectMode2 {
areaOffset := readUInt24(offset + 1)
if areaOffset == 0 {
return []byte("")
} else {
return readString(areaOffset)
}
} else {
return readString(offset)
}
}
func readString(offset uint32) []byte {
data := make([]byte, 0, 30)
for {
if qqwry[offset] == 0 {
break
}
data = append(data, qqwry[offset])
offset++
}
return data
}
func searchIndex(ip uint32) uint32 {
header := qqwry[:8]
start := binary.LittleEndian.Uint32(header[:4])
end := binary.LittleEndian.Uint32(header[4:])
for {
mid := getMiddleOffset(start, end)
buf := qqwry[mid : mid+cIndexLen]
ipaddr := binary.LittleEndian.Uint32(buf[:4])
if end-start == cIndexLen {
offset := byte3ToUInt32(buf[4:])
// TODO: 这里可能有bug需要优化
if ip < binary.LittleEndian.Uint32(qqwry[end:end+4]) {
return offset
} else {
return 0
}
}
// 找到的比较大,向前移
if ipaddr > ip {
end = mid
} else if ipaddr < ip { // 找到的比较小,向后移
start = mid
} else {
return byte3ToUInt32(buf[4:])
}
}
}
func readUInt24(offset uint32) uint32 {
return byte3ToUInt32(qqwry[offset : offset+3])
}
func getMiddleOffset(start uint32, end uint32) uint32 {
records := ((end - start) / cIndexLen) >> 1
return start + records*cIndexLen
}
func byte3ToUInt32(data []byte) uint32 {
i := uint32(data[0]) & 0xff
i |= (uint32(data[1]) << 8) & 0xff00
i |= (uint32(data[2]) << 16) & 0xff0000
return i
}

@ -0,0 +1,25 @@
package iploc
import (
"testing"
)
func TestFind(t *testing.T) {
for _, data := range []struct {
ip string
country string
city string
}{
{ip: "127.0.0.1", country: "本机地址", city: " CZ88.NET"},
{ip: "180.89.94.9", country: "北京市", city: "鹏博士宽带"},
} {
country, city := Find(data.ip)
t.Logf("ip:%v, country:%v, city:%v", data.ip, country, city)
if country != data.country {
t.Errorf("find ip:%s expect country: %s got: %s", data.ip, data.country, country)
}
if city != data.city {
t.Errorf("find ip:%s expect city: %s got: %s", data.ip, data.city, city)
}
}
}

@ -8,6 +8,7 @@ import (
"time"
"github.com/go-resty/resty/v2"
"github.com/rocboss/paopao-ce/pkg/setting"
)
type ZincClient struct {
@ -49,14 +50,17 @@ type QueryResultT struct {
TimedOut bool `json:"timed_out"`
Hits *HitsResultT `json:"hits"`
}
type HitsResultT struct {
Total *HitsResultTotalT `json:"total"`
MaxScore float64 `json:"max_score"`
Hits []*HitItem `json:"hits"`
}
type HitsResultTotalT struct {
Value int64 `json:"value"`
}
type HitItem struct {
Index string `json:"_index"`
Type string `json:"_type"`
@ -66,6 +70,17 @@ type HitItem struct {
Source interface{} `json:"_source"`
}
// NewClient 获取ZincClient新实例
func NewClient(conf *setting.SearchSettingS) *ZincClient {
return &ZincClient{
ZincClientConfig: &ZincClientConfig{
ZincHost: conf.ZincHost,
ZincUser: conf.ZincUser,
ZincPassword: conf.ZincPassword,
},
}
}
// 创建索引
func (c *ZincClient) CreateIndex(name string, p *ZincIndexProperty) bool {
data := &ZincIndex{

1
web/.gitignore vendored

@ -11,6 +11,7 @@ node_modules
dist
dist-ssr
*.local
.env
# Editor directories and files
.vscode/*

@ -0,0 +1,19 @@
//go:build embed
// +build embed
package web
import (
"embed"
"io/fs"
"net/http"
)
//go:embed dist/*
var files embed.FS
// NewFileSystem get an embed static assets http.FileSystem instance.
func NewFileSystem() http.FileSystem {
subfs, _ := fs.Sub(files, "dist")
return http.FS(subfs)
}

@ -5,7 +5,8 @@
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
"preview": "vite preview",
"tauri": "tauri"
},
"dependencies": {
"@vicons/carbon": "^0.12.0",
@ -29,6 +30,7 @@
"vuex": "^4.0.2"
},
"devDependencies": {
"@tauri-apps/cli": "^1.0.0-rc.7",
"@types/node": "^17.0.35",
"@types/qrcode": "^1.4.2",
"@vitejs/plugin-vue": "^2.3.1",

@ -0,0 +1,5 @@
# Generated by Cargo
# will have compiled files and executables
/target/
WixTools
Cargo.lock

@ -0,0 +1,23 @@
[package]
name = "paopao"
version = "0.1.0"
description = "Paopao App"
authors = ["Rocboss"]
license = "MIT License"
repository = "https://github.com/rocboss/paopao-ce"
edition = "2021"
rust-version = "1.57"
[build-dependencies]
tauri-build = { version = "1.0.0-rc.4", features = [] }
[dependencies]
tauri = { version = "1.0.0-rc.4", features = ["api-all"] }
[features]
# by default Tauri runs in production mode
# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL
default = [ "custom-protocol" ]
# this feature is used used for production builds where `devPath` points to the filesystem
# DO NOT remove this
custom-protocol = [ "tauri/custom-protocol" ]

@ -0,0 +1,3 @@
fn main() {
tauri_build::build()
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

@ -0,0 +1,52 @@
#![cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]
use tauri::api::shell;
use tauri::{CustomMenuItem, Manager, Menu, MenuEntry, MenuItem, Submenu};
fn main() {
let _ctx = tauri::generate_context!();
tauri::Builder::default()
.menu(Menu::with_items([
#[cfg(target_os = "macos")]
MenuEntry::Submenu(Submenu::new(
&_ctx.package_info().name,
Menu::with_items([
MenuItem::Separator.into(),
MenuItem::Services.into(),
MenuItem::Separator.into(),
MenuItem::Hide.into(),
MenuItem::HideOthers.into(),
MenuItem::ShowAll.into(),
MenuItem::Separator.into(),
MenuItem::Quit.into(),
]),
)),
MenuEntry::Submenu(Submenu::new(
"Window",
Menu::with_items([MenuItem::Minimize.into(), MenuItem::Zoom.into()]),
)),
// You should always have a Help menu on macOS because it will automatically
// show a menu search field
MenuEntry::Submenu(Submenu::new(
"Help",
Menu::with_items([CustomMenuItem::new("Learn More", "Learn More").into()]),
)),
]))
.on_menu_event(|event| {
let event_name = event.menu_item_id();
event.window().emit("menu", event_name).unwrap();
match event_name {
"Learn More" => {
let link = "https://github.com/rocboss/paopao-ce".to_string();
shell::open(&event.window().shell_scope(), link, None).unwrap();
}
_ => {}
}
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

@ -0,0 +1,74 @@
{
"package": {
"productName": "Paopao",
"version": "0.1.0"
},
"build": {
"distDir": "../dist",
"beforeDevCommand": "",
"beforeBuildCommand": "",
"withGlobalTauri": true
},
"tauri": {
"bundle": {
"active": true,
"targets": "all",
"identifier": "tauri.paopao.info",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
],
"resources": [],
"externalBin": [],
"copyright": "",
"category": "Social Networking",
"shortDescription": "",
"longDescription": "",
"deb": {
"depends": []
},
"macOS": {
"frameworks": [],
"minimumSystemVersion": "",
"exceptionDomain": "",
"signingIdentity": null,
"providerShortName": null,
"entitlements": null
},
"windows": {
"certificateThumbprint": null,
"digestAlgorithm": "sha256",
"timestampUrl": ""
}
},
"updater": {
"active": false
},
"allowlist": {
"all": true,
"http": {
"all": true,
"request": true,
"scope": ["https://**", "http://**"]
},
"notification": {
"all": true
}
},
"windows": [
{
"title": "泡泡 - 闲了,冒个泡",
"width": 1080,
"height": 800,
"resizable": true,
"fullscreen": false
}
],
"security": {
"csp": null
}
}
}

@ -1,62 +1,39 @@
import request from '@/utils/request';
import { request } from '@/utils/request';
/**
*
* @param {Object} params
* - @param {string} username
* - @param {string} password
* @returns Promise
*/
export const userLogin = (params: NetParams.AuthUserLogin = {}) => {
/** 用户登录 */
export const userLogin = (params: NetParams.AuthUserLogin): Promise<NetReq.AuthUserLogin> => {
return request({
method: 'post',
url: '/auth/login',
url: '/v1/auth/login',
data: params,
}) as unknown as Promise<NetReq.AuthUserLogin>;
});
};
/**
*
* @param {Object} params
* - @param {string} username
* - @param {string} password
* @returns Promise
*/
export const userRegister = (params = {}) => {
/** 注册用户 */
export const userRegister = (params: NetParams.AuthUserRegister): Promise<NetReq.AuthUserRegister> => {
return request({
method: 'post',
url: '/auth/register',
url: '/v1/auth/register',
data: params,
});
};
/**
*
* @param {Object} params
* @returns Promise
*/
export const userInfo = (token = '') => {
/** 用户信息 */
export const userInfo = (token: NetParams.AuthUserInfo = ""): Promise<NetReq.AuthUserInfo> => {
return request({
method: 'get',
url: '/user/info',
url: '/v1/user/info',
headers: {
Authorization: `Bearer ${token}`,
},
});
};
/**
*
* @param {Object} params
* - @param {string} password
* - @param {string} old_password
* @returns Promise
*/
export const updateUserPassword = (data: any) => {
/** 修改用户密码,该接口暂时未使用 */
export const updateUserPassword = (data: NetParams.AuthUpdateUserPassword): Promise<NetReq.AuthUpdateUserPassword> => {
return request({
method: 'post',
url: '/api/user/password',
url: '/v1/api/user/password',
data,
});
};

@ -1,222 +1,145 @@
import request from '@/utils/request';
import { request } from '@/utils/request';
/**
*
* @param {Object} params
* @returns Promise
*/
export const getPosts = (params: NetParams.PostGetPosts) => {
/** 获取动态列表 */
export const getPosts = (params: NetParams.PostGetPosts): Promise<NetReq.PostGetPosts> => {
return request({
method: 'get',
url: '/posts',
url: '/v1/posts',
params
}) as unknown as Promise<NetReq.PostGetPosts>;
});
};
/**
*
* @param {Object} params
* @returns Promise
*/
export const getTags = (params: NetParams.PostGetTags) => {
/** 获取标签列表 */
export const getTags = (params: NetParams.PostGetTags): Promise<NetReq.PostGetTags> => {
return request({
method: 'get',
url: '/tags',
url: '/v1/tags',
params
}) as unknown as Promise<NetReq.PostGetTags>;
});
};
/**
*
* @param {Object} params
* @returns Promise
*/
export const getPost = (params: NetParams.PostGetPost) => {
/** 获取动态详情 */
export const getPost = (params: NetParams.PostGetPost): Promise<NetReq.PostGetPost> => {
return request({
method: 'get',
url: '/post',
url: '/v1/post',
params
}) as unknown as Promise<NetReq.PostGetPost>;
});
};
/**
*
* @param {Object} params
* @returns Promise
*/
export const getPostStar = (params: NetParams.PostPostStar) => {
/** 获取动态点赞状态 */
export const getPostStar = (params: NetParams.PostPostStar): Promise<NetReq.PostGetPostStar> => {
return request({
method: 'get',
url: '/post/star',
url: '/v1/post/star',
params
}) as unknown as Promise<NetReq.PostGetPostStar>;
});
};
/**
*
* @param {Object} data
* @returns Promise
*/
export const postStar = (data: NetParams.PostPostStar) => {
/** 动态点赞 */
export const postStar = (data: NetParams.PostPostStar): Promise<NetReq.PostPostStar> => {
return request({
method: 'post',
url: '/post/star',
url: '/v1/post/star',
data
}) as unknown as Promise<NetReq.PostPostStar>;
});
};
/**
*
* @param {Object} params
* @returns Promise
*/
export const getPostCollection = (params: NetParams.PostGetPostCollection) => {
/** 获取动态收藏状态 */
export const getPostCollection = (params: NetParams.PostGetPostCollection): Promise<NetReq.PostGetPostCollection> => {
return request({
method: 'get',
url: '/post/collection',
url: '/v1/post/collection',
params
}) as unknown as Promise<NetReq.PostGetPostCollection>;
});
};
/**
*
* @param {Object} data
* @returns Promise
*/
export const postCollection = (data: NetParams.PostPostCollection) => {
/** 动态收藏 */
export const postCollection = (data: NetParams.PostPostCollection): Promise<NetReq.PostPostCollection> => {
return request({
method: 'post',
url: '/post/collection',
url: '/v1/post/collection',
data
}) as unknown as Promise<NetReq.PostPostCollection>;
});
};
/**
*
* @param {Object} params
* @returns Promise
*/
export const getPostComments = (params: NetParams.PostGetPostComments) => {
/** 获取动态评论列表 */
export const getPostComments = (params: NetParams.PostGetPostComments): Promise<NetReq.PostGetPostComments> => {
return request({
method: 'get',
url: '/post/comments',
url: '/v1/post/comments',
params
}) as unknown as Promise<NetReq.PostGetPostComments>;
});
};
/**
*
* @param {Object} data
* - @param {array} contents
* - @param {array} users at
* - @param {array} tags
* @returns Promise
*/
export const createPost = (data: NetParams.PostCreatePost) => {
/** 发布动态 */
export const createPost = (data: NetParams.PostCreatePost): Promise<NetReq.PostCreatePost> => {
return request({
method: 'post',
url: '/post',
url: '/v1/post',
data
}) as unknown as Promise<NetReq.PostCreatePost>;
});
};
/**
*
* @param {Object} data
* - @param {number} id
* @returns Promise
*/
export const deletePost = (data: any) => {
/** 删除动态 */
export const deletePost = (data: NetParams.PostDeletePost): Promise<NetReq.PostDeletePost> => {
return request({
method: 'delete',
url: '/post',
url: '/v1/post',
data
});
};
/**
* /
* @param {Object} data
* - @param {number} id
* @returns Promise
*/
export const lockPost = (data: NetParams.PostLockPost) => {
/** 锁定/解锁动态 */
export const lockPost = (data: NetParams.PostLockPost): Promise<NetReq.PostLockPost> => {
return request({
method: 'post',
url: '/post/lock',
url: '/v1/post/lock',
data
}) as unknown as Promise<NetReq.PostLockPost>;
});
};
/**
* /
* @param {Object} data
* - @param {number} id
* @returns Promise
*/
export const stickPost = (data: NetParams.PostStickPost) => {
/** 置顶/取消置顶动态 */
export const stickPost = (data: NetParams.PostStickPost): Promise<NetReq.PostStickPost> => {
return request({
method: 'post',
url: '/post/stick',
url: '/v1/post/stick',
data
}) as unknown as Promise<NetReq.PostStickPost>;
});
};
/**
*
* @param {Object} data
* - @param {array} contents
* - @param {array} users at
* @returns Promise
*/
export const createComment = (data: any) => {
/** 发布动态评论 */
export const createComment = (data: NetParams.PostCreateComment): Promise<NetReq.PostCreateComment> => {
return request({
method: 'post',
url: '/post/comment',
url: '/v1/post/comment',
data
});
};
/**
*
* @param {Object} data
* - @param {number} id
* @returns Promise
*/
export const deleteComment = (data: any) => {
/** 删除评论 */
export const deleteComment = (data: NetParams.PostDeleteComment): Promise<NetReq.PostDeleteComment> => {
return request({
method: 'delete',
url: '/post/comment',
url: '/v1/post/comment',
data
});
};
/**
*
* @param {Object} data
* - @param {string} content
* - @param {number} comment_id ID
* - @param {number} at_user_id atID
* @returns Promise
*/
export const createCommentReply = (data: any) => {
/** 发布评论回复 */
export const createCommentReply = (data: NetParams.PostCreateCommentReply): Promise<NetReq.PostCreateCommentReply> => {
return request({
method: 'post',
url: '/post/comment/reply',
url: '/v1/post/comment/reply',
data
});
};
/**
*
* @param {Object} data
* - @param {number} id ID
* @returns Promise
*/
export const deleteCommentReply = (data: any) => {
/** 删除评论回复 */
export const deleteCommentReply = (data: NetParams.PostDeleteCommentReply): Promise<NetReq.PostDeleteCommentReply> => {
return request({
method: 'delete',
url: '/post/comment/reply',
url: '/v1/post/comment/reply',
data
});
};
};

@ -1,16 +1,12 @@
import request from '@/utils/request';
import { request } from '@/utils/request';
/**
*
* @param {Object} params
* @returns Promise
*/
export const getCaptcha = (params: NetParams.UserGetCaptcha = {}) => {
/** 获取验证码 */
export const getCaptcha = (params: NetParams.UserGetCaptcha = {}): Promise<NetReq.UserGetCaptcha> => {
return request({
method: 'get',
url: '/captcha',
url: '/v1/captcha',
params
}) as unknown as Promise<NetReq.UserGetCaptcha>;
});
};
/**
@ -21,7 +17,7 @@ export const getCaptcha = (params: NetParams.UserGetCaptcha = {}) => {
export const sendCaptcha = (data: any) => {
return request({
method: 'post',
url: '/captcha',
url: '/v1/captcha',
data
});
};
@ -31,12 +27,12 @@ export const sendCaptcha = (data: any) => {
* @param {Object} data
* @returns Promise
*/
export const sendUserWhisper = (data: NetParams.UserWhisper) => {
export const sendUserWhisper = (data: NetParams.UserWhisper): Promise<NetParams.UserWhisper> => {
return request({
method: 'post',
url: '/user/whisper',
url: '/v1/user/whisper',
data
}) as unknown as Promise<NetParams.UserWhisper>;
});
};
/**
@ -44,36 +40,28 @@ export const sendUserWhisper = (data: NetParams.UserWhisper) => {
* @param {Object} data
* @returns Promise
*/
export const bindUserPhone = (data: NetParams.UserBindUserPhone) => {
export const bindUserPhone = (data: NetParams.UserBindUserPhone): Promise<NetParams.UserBindUserPhone> => {
return request({
method: 'post',
url: '/user/phone',
url: '/v1/user/phone',
data
}) as unknown as Promise<NetParams.UserBindUserPhone>;
});
};
/**
*
* @param {Object} data
* @returns Promise
*/
export const changePassword = (data: any) => {
/** 更改密码 */
export const changePassword = (data: NetParams.UserChangePassword): Promise<NetReq.UserChangePassword> => {
return request({
method: 'post',
url: '/user/password',
url: '/v1/user/password',
data
});
};
/**
*
* @param {Object} data
* @returns Promise
*/
export const changeNickname = (data: any) => {
/** 更改昵称 */
export const changeNickname = (data: NetParams.UserChangeNickname): Promise<NetReq.UserChangeNickname> => {
return request({
method: 'post',
url: '/user/nickname',
url: '/v1/user/nickname',
data
});
};
@ -86,35 +74,27 @@ export const changeNickname = (data: any) => {
export const changeAvatar = (data: any) => {
return request({
method: 'post',
url: '/user/avatar',
url: '/v1/user/avatar',
data
});
};
/**
*
* @param {Object} params
* @returns Promise
*/
export const getUnreadMsgCount = (params: NetParams.UserGetUnreadMsgCount = {}) => {
/** 获取未读消息数 */
export const getUnreadMsgCount = (params: NetParams.UserGetUnreadMsgCount = {}): Promise<NetReq.UserGetUnreadMsgCount> => {
return request({
method: 'get',
url: '/user/msgcount/unread',
url: '/v1/user/msgcount/unread',
params
}) as unknown as Promise<NetReq.UserGetUnreadMsgCount>;
});
};
/**
*
* @param {Object} params
* @returns Promise
*/
export const getMessages = (params: NetParams.UserGetMessages) => {
/** 获取消息列表 */
export const getMessages = (params: NetParams.UserGetMessages): Promise<NetReq.UserGetMessages> => {
return request({
method: 'get',
url: '/user/messages',
url: '/v1/user/messages',
params
}) as unknown as Promise<NetReq.UserGetMessages>;
});
};
/**
@ -125,74 +105,54 @@ export const getMessages = (params: NetParams.UserGetMessages) => {
export const readMessage = (data: any) => {
return request({
method: 'post',
url: '/user/message/read',
url: '/v1/user/message/read',
data
});
};
/**
*
* @param {Object} params
* @returns Promise
*/
export const getCollections = (params: NetParams.UserGetCollections) => {
/** 获取收藏列表 */
export const getCollections = (params: NetParams.UserGetCollections): Promise<NetReq.UserGetCollections> => {
return request({
method: 'get',
url: '/user/collections',
url: '/v1/user/collections',
params
}) as unknown as Promise<NetReq.UserGetCollections>;
});
};
/**
*
* @param {Object} params
* @returns Promise
*/
export const getStars = (params: NetParams.UserGetStars) => {
/** 获取点赞列表 */
export const getStars = (params: NetParams.UserGetStars): Promise<NetReq.UserGetStars> => {
return request({
method: 'get',
url: '/user/stars',
url: '/v1/user/stars',
params
}) as unknown as Promise<NetReq.UserGetStars>;
});
};
/**
*
* @param {Object} params
* @returns Promise
*/
export const getUserProfile = (params: NetParams.UserGetUserProfile) => {
/** 获取用户基础信息 */
export const getUserProfile = (params: NetParams.UserGetUserProfile): Promise<NetReq.UserGetUserProfile> => {
return request({
method: 'get',
url: '/user/profile',
url: '/v1/user/profile',
params
}) as unknown as Promise<NetReq.UserGetUserProfile>;
});
};
/**
*
* @param {Object} params
* @returns Promise
*/
export const getUserPosts = (params: NetParams.UserGetUserPosts) => {
/** 获取用户帖子列表 */
export const getUserPosts = (params: NetParams.UserGetUserPosts): Promise<NetReq.UserGetUserPosts> => {
return request({
method: 'get',
url: '/user/posts',
url: '/v1/user/posts',
params
}) as unknown as Promise<NetReq.UserGetUserPosts>;
});
};
/**
*
* @param {Object} params
* @returns Promise
*/
export const getBills = (params: NetParams.UserGetBills) => {
/** 获取账单列表 */
export const getBills = (params: NetParams.UserGetBills): Promise<NetReq.UserGetBills> => {
return request({
method: 'get',
url: '/user/wallet/bills',
url: '/v1/user/wallet/bills',
params
}) as unknown as Promise<NetReq.UserGetBills>;
});
};
/**
@ -200,12 +160,12 @@ export const getBills = (params: NetParams.UserGetBills) => {
* @param {Object} data
* @returns Promise
*/
export const reqRecharge = (data: NetParams.UserReqRecharge) => {
export const reqRecharge = (data: NetParams.UserReqRecharge): Promise<NetReq.UserReqRecharge> => {
return request({
method: 'post',
url: '/user/recharge',
url: '/v1/user/recharge',
data
}) as unknown as Promise<NetReq.UserReqRecharge>;
});
};
/**
@ -213,12 +173,12 @@ export const reqRecharge = (data: NetParams.UserReqRecharge) => {
* @param {Object} params
* @returns Promise
*/
export const getRecharge = (params: NetParams.UserGetRecharge) => {
export const getRecharge = (params: NetParams.UserGetRecharge): Promise<NetReq.UserGetRecharge> => {
return request({
method: 'get',
url: '/user/recharge',
url: '/v1/user/recharge',
params
}) as unknown as Promise<NetReq.UserGetRecharge>;
});
};
/**
@ -226,12 +186,12 @@ export const getRecharge = (params: NetParams.UserGetRecharge) => {
* @param {Object} params
* @returns Promise
*/
export const getSuggestUsers = (params: { k: string }) => {
export const getSuggestUsers = (params: { k: string }): Promise<NetReq.UserGetSuggestUsers> => {
return request({
method: 'get',
url: '/suggest/users',
url: '/v1/suggest/users',
params
}) as unknown as Promise<NetReq.UserGetSuggestUsers>;
});
};
/**
@ -239,12 +199,12 @@ export const getSuggestUsers = (params: { k: string }) => {
* @param {Object} params
* @returns Promise
*/
export const getSuggestTags = (params: { k: string }) => {
export const getSuggestTags = (params: { k: string }): Promise<NetReq.UserGetSuggestTags> => {
return request({
method: 'get',
url: '/suggest/tags',
url: '/v1/suggest/tags',
params
}) as unknown as Promise<NetReq.UserGetSuggestTags>;
});
};
/**
@ -252,12 +212,12 @@ export const getSuggestTags = (params: { k: string }) => {
* @param {Object} params
* @returns Promise
*/
export const precheckAttachment = (params: NetParams.UserPrecheckAttachment) => {
export const precheckAttachment = (params: NetParams.UserPrecheckAttachment): Promise<NetReq.UserPrecheckAttachment> => {
return request({
method: 'get',
url: '/attachment/precheck',
url: '/v1/attachment/precheck',
params
}) as unknown as Promise<NetReq.UserPrecheckAttachment>;
});
};
/**
@ -265,10 +225,10 @@ export const precheckAttachment = (params: NetParams.UserPrecheckAttachment) =>
* @param {Object} params
* @returns Promise
*/
export const getAttachment = (params: NetParams.UserGetAttachment) => {
export const getAttachment = (params: NetParams.UserGetAttachment): Promise<NetReq.UserGetAttachment> => {
return request({
method: 'get',
url: '/attachment',
url: '/v1/attachment',
params
}) as unknown as Promise<NetReq.UserGetAttachment>;
});
};

@ -113,20 +113,20 @@ const replyAtUsername = ref('');
const replyComposeRef = ref();
const emit = defineEmits<{
(e: "reload"): void
(e: 'reload'): void
}>();
const props = withDefaults(defineProps<{
comment: Item.CommentProps
}>(), {})
const comment = computed(() => {
let comment = Object.assign(
let comment: Item.CommentComponentProps = Object.assign(
{
texts: [],
imgs: [],
},
props.comment
) as {texts: Item.CommentProps[], imgs: Item.CommentProps[]} & Item.CommentProps;
);
comment.contents.map((content :any) => {
if (+content.type === 1 || +content.type === 2) {
comment.texts.push(content);

@ -170,7 +170,7 @@ import { parsePostTag } from '@/utils/content';
import type { MentionOption, UploadFileInfo, UploadInst } from 'naive-ui';
const emit = defineEmits<{
(e: "post-success"): void
(e: 'post-success'): void
}>();
const props = withDefaults(defineProps<{
lock: number,
@ -265,7 +265,7 @@ const finishUpload = ({ file, event }: any): any => {
imageContents.value.push({
id: file.id,
content: data.data.content,
});
} as Item.CommentItemProps);
}
}
} catch (error) {

@ -50,11 +50,11 @@ const props = withDefaults(defineProps<{
}>(), {
commentId: 0,
atUserid: 0,
atUsername: ""
atUsername: ''
});
const emit = defineEmits<{
(e: "reload"): void,
(e: "reset"): void
(e: 'reload'): void,
(e: 'reset'): void
}>();
const inputInstRef = ref<InputInst>();
const showReply = ref(false);

@ -265,7 +265,7 @@ const uploadType = ref('public/image');
const fileQueue = ref<UploadFileInfo[]>([]);
const imageContents = ref<Item.CommentItemProps[]>([]);
const videoContents = ref<Item.CommentItemProps[]>([]);
const attachmentContents = ref<Item.CommentItemProps[]>([]);
const attachmentContents = ref<Item.AttachmentProps[]>([]);
const uploadGateway = import.meta.env.VITE_HOST + '/attachment';
const uploadToken = ref();
@ -402,19 +402,19 @@ const finishUpload = ({ file, event }: any): any => {
imageContents.value.push({
id: file.id,
content: data.data.content,
});
} as Item.CommentItemProps);
}
if (uploadType.value === 'public/video') {
videoContents.value.push({
id: file.id,
content: data.data.content,
});
} as Item.CommentItemProps);
}
if (uploadType.value === 'attachment') {
attachmentContents.value.push({
id: file.id,
content: data.data.content,
});
} as Item.AttachmentProps);
}
}
} catch (error) {

@ -46,11 +46,11 @@
<template #description>
<n-alert
:show-icon="false"
class="breif-wrap"
class="brief-wrap"
:type="message.is_read > 0 ? 'default' : 'success'"
>
<div class="breif-content">
{{ message.breif }}
<div class="brief-content">
{{ message.brief }}
<span
v-if="message.type !== 4"
@click.stop="viewDetail(message)"
@ -146,9 +146,9 @@ const handleReadMessage = (message: Item.MessageProps) => {
}
}
.breif-wrap {
.brief-wrap {
margin-top: 10px;
.breif-content {
.brief-content {
display: flex;
width: 100%;
}

@ -42,7 +42,7 @@ import { precheckAttachment, getAttachment } from '@/api/user';
const props = withDefaults(
defineProps<{
attachments: Item.AttachmentProps[];
attachments: Item.PostItemProps[];
price?: number;
}>(),
{
@ -54,7 +54,7 @@ const showDownloadModal = ref(false);
const downloadTip = ref<any>('');
const attachmentID = ref(0);
const download = (attachment: Item.AttachmentProps) => {
const download = (attachment: Item.PostItemProps) => {
showDownloadModal.value = true;
attachmentID.value = attachment.id;

@ -197,7 +197,7 @@ const emit = defineEmits<{
const post = computed({
get: () => {
let post: Required<Item.PostProps> = Object.assign(
let post: Item.PostComponentProps = Object.assign(
{
texts: [],
imgs: [],

@ -230,7 +230,7 @@ const defaultImg =
const thumbnail =
'?x-oss-process=image/resize,m_fill,w_300,h_300,limit_0/auto-orient,1/format,png';
const props = withDefaults(defineProps<{
imgs: Item.PostProps[],
imgs: Item.PostItemProps[],
}>(), {
imgs: () => []
});

@ -101,7 +101,7 @@ const props = withDefaults(defineProps<{
}>(), {});
const post = computed(() => {
let post: Required<Item.PostProps> = Object.assign(
let post: Item.PostComponentProps = Object.assign(
{
texts: [],
imgs: [],

@ -17,7 +17,7 @@
<script setup lang="ts">
import { LinkOutline } from '@vicons/ionicons5';
const props = withDefaults(defineProps<{
links: Item.PostProps[]
links: Item.PostItemProps[]
}>(), {
links: () => []
});

@ -22,7 +22,7 @@ import NVideo from 'nonesir-video';
const props = withDefaults(
defineProps<{
videos: Item.PostProps[];
videos: Item.PostItemProps[];
full?: boolean;
}>(),
{

@ -76,8 +76,8 @@ const props = withDefaults(defineProps<{
}>(), {});
const store = useStore();
const emit = defineEmits<{
(e: "focusReply", reply: Item.ReplyProps): void,
(e: "reload"): void
(e: 'focusReply', reply: Item.ReplyProps): void,
(e: 'reload'): void
}>();
const focusReply = () => {

@ -1,8 +1,26 @@
declare module NetParams {
interface AuthUserLogin {
username?: string,
password?: string
/** 用户名 */
username: string,
/** 密码 */
password: string
}
interface AuthUserRegister {
/** 用户名 */
username: string,
/** 密码 */
password: string
}
type AuthUserInfo = string
interface AuthUpdateUserPassword {
/** 新密码 */
password: string,
/** 旧密码 */
old_password: string
}
interface UserGetCollections {
@ -28,6 +46,7 @@ declare module NetParams {
}
interface UserGetUserPosts {
/** 用户名 */
username: string,
page: number,
page_size: number
@ -69,13 +88,25 @@ declare module NetParams {
content: string
}
interface UserChangePassword {
/** 新密码 */
password: string,
/** 旧密码 */
old_password: string
}
interface UserChangeNickname {
/** 昵称 */
nickname: string
}
interface PostGetPost {
id: number
}
interface PostGetPosts {
query: string | null,
type: number,
type: string,
page: number,
page_size: number
}
@ -92,11 +123,11 @@ declare module NetParams {
id: number
}
interface PostGetPostCollection {
interface PostPostStar {
id: number
}
interface PostPostStar {
interface PostGetPostCollection {
id: number
}
@ -105,7 +136,7 @@ declare module NetParams {
}
interface PostGetTags {
type: "hot" | string,
type: 'hot' | string,
num: number
}
@ -114,14 +145,44 @@ declare module NetParams {
}
interface PostCreatePost {
contents: {
content: string,
type: number,
sort: number
}[],
/** 帖子内容列表 */
contents: Partial<Item.PostItemProps>[],
/** 标签列表 */
tags: string[],
/** 艾特用户列表 */
users: string[],
/** 附件价格 */
attachment_price: number
}
}
interface PostDeletePost {
id: number
}
interface PostCreateComment {
/** 内容ID */
post_id: number,
/** 帖子内容列表 */
contents: Partial<Item.CommentItemProps>[],
/** 艾特用户列表 */
users: string[]
}
interface PostDeleteComment {
id: number
}
interface PostCreateCommentReply {
/** 艾特的用户UID */
at_user_id: number,
/** 回复的评论ID */
comment_id: number,
/** 回复内容 */
content: string
}
interface PostDeleteCommentReply{
id: number
}
}

@ -1,12 +1,27 @@
declare module NetReq {
interface AuthUserLogin {
token?: string
token: string
}
interface AuthUserRegister {
/** 用户UID */
id: number,
/** 用户名 */
username: string
}
type AuthUserInfo = Item.UserInfo
interface AuthUpdateUserPassword {
}
interface UserGetCollections {
list: any[],
pager: AnyObject
/** 帖子列表 */
list: Item.PostProps[],
/** 页码信息 */
pager: Item.PagerProps
}
type UserGetSuggestUsers = string[]
@ -23,17 +38,23 @@ declare module NetReq {
}
interface UserGetMessages {
/** 消息列表 */
list: Item.MessageProps[],
/** 页码信息 */
pager: Item.PagerProps
}
interface UserGetUserPosts {
/** 帖子列表 */
list: Item.PostProps[],
/** 页码信息 */
pager: Item.PagerProps
}
interface UserGetStars {
/** 帖子列表 */
list: Item.PostProps[],
/** 页码信息 */
pager: Item.PagerProps
}
@ -41,6 +62,7 @@ declare module NetReq {
interface UserGetBills {
list: Item.BillProps[],
/** 页码信息 */
pager: Item.PagerProps
}
@ -59,33 +81,46 @@ declare module NetReq {
interface UserGetCaptcha {
id: string,
/** 头像图片 base64 */
b64s: string
}
interface UserChangeNickname {
}
interface UserChangePassword {
}
type PostGetPost = Item.PostProps
interface PostGetPosts {
/** 帖子列表 */
list: Item.PostProps[],
/** 页码信息 */
pager: Item.PagerProps
}
interface PostLockPost {
lock_status: number
/** 锁定状态0为未锁定1为锁定 */
lock_status: 0 | 1
}
interface PostStickPost {
top_status: number
/** 置顶状态0为未置顶1为置顶 */
top_status: 0 | 1
}
interface PostGetPostStar {
status: boolean
}
interface PostGetPostCollection {
interface PostPostStar {
status: boolean
}
interface PostPostStar {
interface PostGetPostCollection {
status: boolean
}
@ -96,9 +131,28 @@ declare module NetReq {
type PostGetTags = Item.TagProps[]
interface PostGetPostComments {
list: Item.PostProps[]
/** 评论列表 */
list: Item.CommentProps[],
/** 页码信息 */
pager: Item.PagerProps
}
type PostCreatePost = Item.PostProps
}
interface PostDeletePost {
}
type PostCreateComment = Item.CommentProps
interface PostDeleteComment {
}
type PostCreateCommentReply = Item.ReplyProps
interface PostDeleteCommentReply{
}
}

@ -1,85 +1,282 @@
declare module Item {
interface UserInfo {
/** 用户UID */
id: number,
/** 用户名 */
username: string,
/** 用户昵称 */
nickname: string,
avatar: string
/** 用户头像 */
avatar: string,
/** 用户手机号 */
phone?: string,
/** 是否为管理员 */
is_admin: boolean,
/** 用户余额(分) */
balance?: number,
/** 用户状态 */
status?: 0 | 1
}
/** 评论内容 */
interface CommentItemProps {
id: number | string,
content: string
/** 内容ID */
id: number,
/** 评论ID */
comment_id: number,
/** 评论者UID */
user_id: number,
/** 类别1为标题2为文字段落3为图片地址4为视频地址5为语音地址6为链接地址 */
type: number,
/** 内容 */
content: string,
/** 排序,越小越靠前 */
sort: number,
/** 创建时间 */
created_on: number,
/** 修改时间 */
modified_on?: number,
/** 删除时间 */
deleted_on?: number,
/** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1
}
interface CommentProps extends CommentItemProps {
type: number,
/** 评论数据 */
interface CommentProps {
id: number,
post_id: number,
/** 评论者UID */
user_id: number,
/** 评论者用户信息 */
user: UserInfo,
contents: CommentProps[],
/** 评论内容 */
contents: CommentItemProps[],
/** 回复列表 */
replies: ReplyProps[],
/** 评论者IP地址 */
ip?: string,
/** 评论者城市地址 */
ip_loc: string,
created_on: number
/** 创建时间 */
created_on: number,
/** 修改时间 */
modified_on?: number,
/** 删除时间 */
deleted_on?: number,
/** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1
}
interface CommentComponentProps extends CommentProps {
/** 文字评论列表 */
texts: CommentItemProps[],
/** 图片评论列表 */
imgs: CommentItemProps[]
}
/** 回复内容 */
interface ReplyProps {
/** 内容ID */
id: number,
/** 评论ID */
comment_id: number,
/** 回复人ID */
user_id: number,
/** 回复人用户数据 */
user: UserInfo,
/** 艾特人ID */
at_user_id: number,
/** 艾特人用户数据 */
at_user: UserInfo,
/** 内容 */
content: string,
/** 回复人IP地址 */
ip?: string,
/** 回复人城市地址 */
ip_loc: string,
created_on: number
/** 创建时间 */
created_on: number,
/** 修改时间 */
modified_on?: number,
/** 删除时间 */
deleted_on?: number,
/** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1
}
interface PostProps {
/** 帖子内容 */
interface PostItemProps {
/** 内容ID */
id: number,
/** 类型1为标题2为文字段落3为图片地址4为视频地址5为语音地址6为链接地址7为附件资源8为收费资源 */
type: number,
/** POST ID */
post_id: number,
/** 内容 */
content: string,
/** 排序,越小越靠前 */
sort: number,
/** 用户UID */
user_id?: number,
/** 创建时间 */
created_on: number,
/** 修改时间 */
modified_on?: number,
/** 删除时间 */
deleted_on?: number,
/** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1,
}
/** 帖子 */
interface PostProps {
id: number,
/** 发帖人UID */
user_id: number,
/** 发帖人用户数据 */
user: UserInfo,
/** 附件价格(分) */
attachment_price: number,
/** 发帖时IP地址 */
ip?: string,
/** 发帖时城市地址 */
ip_loc: string,
created_on: number,
/** 最新回复时间 */
latest_replied_on: number,
/** 创建时间 */
created_on: number,
/** 修改时间 */
modified_on?: number,
/** 删除时间 */
deleted_on?: number,
/** 点赞数 */
upvote_count: number,
/** 评论数 */
comment_count: number,
/** 收藏数 */
collection_count: number,
content: string,
contents: PostProps[],
/** 内容列表 */
contents: PostItemProps[],
/** 标签列表 */
tags: {[key: string]: number} | string,
/** 是否锁定 */
is_lock: number,
/** 是否置顶 */
is_top: number,
texts?: PostProps[],
imgs?: PostProps[],
videos?: PostProps[],
links?: PostProps[],
attachments?: PostProps[],
charge_attachments?: PostProps[]
/** 是否精华 */
is_essence: number,
/** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1
}
/** 组件用帖子 */
interface PostComponentProps extends PostProps {
/** 文字段落列表 */
texts: PostItemProps[],
/** 图片列表 */
imgs: PostItemProps[],
/** 视频列表 */
videos: PostItemProps[],
/** 链接列表 */
links: PostItemProps[],
/** 附件列表 */
attachments: PostItemProps[],
/** 收费附件列表 */
charge_attachments: PostItemProps[]
}
interface MessageProps {
id: number,
type: number,
is_read: number,
sender_user: UserInfo
post: PostProps,
/** 类型1为动态2为评论3为回复4为私信99为系统通知 */
type: 1 | 2 | 3 | 4 | 99,
/** 摘要说明 */
brief: string,
/** 详细内容 */
content: string,
/** 是否已读0为未读1为已读 */
is_read: 0 | 1,
/** 发送人UID */
sender_user_id: number,
/** 发送人用户数据 */
sender_user: UserInfo,
/** 接收方UID */
receiver_user_id: number,
/** 帖子ID */
post_id: number,
/** 帖子内容 */
post: PostProps,
/** 评论ID */
comment_id: number,
/** 评论内容 */
comment: CommentProps,
/** 回复ID */
reply_id: number,
/** 回复内容 */
replay: ReplyProps,
/** 创建时间 */
created_on: number,
breif: string
content?: string
/** 修改时间 */
modified_on?: number,
/** 删除时间 */
deleted_on?: number,
/** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1
}
interface AttachmentProps {
id: number,
type: number
/** 类别1为图片2为视频3为其他附件 */
type: 1 | 2 | 3,
/** 发布者用户UID */
user_id: number,
/** 发布者用户数据 */
user: UserInfo,
/** 文件大小 */
file_size: number,
/** 图片宽度 */
img_width?: number,
/** 图片高度 */
img_height?: number,
/** 内容 */
content: string,
/** 创建时间 */
created_on: number,
/** 修改时间 */
modified_on?: number,
/** 删除时间 */
deleted_on?: number,
/** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1
}
interface TagProps {
id: number,
quote_num: number,
/** 创建者UID */
user_id: number,
/** 创建者用户数据 */
user: UserInfo,
/** 标签名 */
tag: string,
user: UserInfo
/** 引用数 */
quote_num: number,
/** 创建时间 */
created_on: number,
/** 修改时间 */
modified_on?: number,
/** 删除时间 */
deleted_on?: number,
/** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1
}
interface PagerProps {
/** 当前页码 */
page: number,
/** 每页条数 */
page_size: number,
/** 总条数 */
total_rows: number
}

@ -1,4 +1,4 @@
import axios from 'axios';
import axios, { AxiosRequestConfig, AxiosRequestHeaders, Method } from 'axios';
const service = axios.create({
baseURL: import.meta.env.VITE_HOST,
@ -48,3 +48,7 @@ service.interceptors.response.use(
);
export default service;
export function request<T, R>(config: AxiosRequestConfig<T>): Promise<R> {
return service(config) as unknown as Promise<R>;
}

@ -67,7 +67,7 @@ const loadPosts = () => {
loading.value = true;
getPosts({
query: route.query.q ? decodeURIComponent(route.query.q as string) : null,
type: +(route.query.t as string),
type: route.query.t as string,
page: page.value,
page_size: pageSize.value,
})

@ -54,7 +54,7 @@ const route = useRoute();
const post = ref<Item.PostProps>({} as Item.PostProps);
const loading = ref(false);
const commentLoading = ref(false);
const comments = ref<Item.PostProps[]>([]);
const comments = ref<Item.CommentProps[]>([]);
const postId = computed(() => +(route.query.id as string));
const loadPost = () => {

@ -285,9 +285,9 @@ const modelData = reactive({
imgCaptcha: '',
phone: '',
phone_captcha: '',
password: null,
old_password: null,
reenteredPassword: null,
password: '',
old_password: '',
reenteredPassword: '',
});
const beforeUpload = async (data: any) => {

@ -84,6 +84,66 @@
estree-walker "^2.0.1"
picomatch "^2.2.2"
"@tauri-apps/cli-darwin-arm64@1.0.0-rc.13":
version "1.0.0-rc.13"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.0.0-rc.13.tgz#da73a770835ffd63a149d8becf50d3781e1c97dd"
integrity sha512-/EqOz7ASHOU98H58Ibbkg12pLG/P5oyQz8OlueaMYryajkJdmi+bHTkJ05DfbS0owAaHkRJ6f+NmoW/AnyqUbg==
"@tauri-apps/cli-darwin-x64@1.0.0-rc.13":
version "1.0.0-rc.13"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.0.0-rc.13.tgz#e120cc623fddca3eb9d7fea0c2de057c7440a821"
integrity sha512-bvZ0MBKFD1kc4gdVPXgwUA6tHNKj0EmlQK0Xolk6PYP9vZZeNTP1vejevW0bh2IqxC8DuqUArbG9USXwu+LFbQ==
"@tauri-apps/cli-linux-arm-gnueabihf@1.0.0-rc.13":
version "1.0.0-rc.13"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.0.0-rc.13.tgz#3052a59788ae57ad690d4bc09bf0756bc8808116"
integrity sha512-yODvfUkNvtYYdDTOJSDXMx9fpoEB66I2PTrYx1UKonKTEaLrQDcpw2exD/S9LPQzCYgyTuJ/kHRhG1uLdO/UUQ==
"@tauri-apps/cli-linux-arm64-gnu@1.0.0-rc.13":
version "1.0.0-rc.13"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.0.0-rc.13.tgz#9c4094473890c165a4fb22132229ed8212559f79"
integrity sha512-kVDJHERD8CmTeMcd2VTnD/nVCHdnNAK8a6ur3l0KTR1iF8A1AtN/sPahMQjK4f7Ar00UDjIzTw74liqakOeiZg==
"@tauri-apps/cli-linux-arm64-musl@1.0.0-rc.13":
version "1.0.0-rc.13"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.0.0-rc.13.tgz#16270a6d3b9289993b9b4d837f63dba4991d9be5"
integrity sha512-PFHz+0xKCGMqqn2TmbOSPvTRS61xJQV7srwTZjs5sHBvK536mdBnF/6V6BPEvTn5LzfRnxMu2A5X5GFkYnrZ7w==
"@tauri-apps/cli-linux-x64-gnu@1.0.0-rc.13":
version "1.0.0-rc.13"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.0.0-rc.13.tgz#d2f5031f9597300a5814dc8b4d3c59e8dc25a871"
integrity sha512-EWhTOUNHaaMM7mxp/ue+Osnzn6/o9/7qVle3MSnNI9pGQzumc/dOtBs+sWS/NPXdVEiWKET2mFMK120KJlYcQQ==
"@tauri-apps/cli-linux-x64-musl@1.0.0-rc.13":
version "1.0.0-rc.13"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.0.0-rc.13.tgz#9d8b02de7bd5af71c5d3d5be96ec88f3f29c8fbd"
integrity sha512-i8lsKw5iAGTAhqSQHeUCISLjhRXNrloHPoFCaSZtU0/GAPGbW/qST7u593h7cKWxRooeMwzo74ij4GhgmddClQ==
"@tauri-apps/cli-win32-ia32-msvc@1.0.0-rc.13":
version "1.0.0-rc.13"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.0.0-rc.13.tgz#1fcf6bed5a89af2cb30a2fe2e823ca486ded61b7"
integrity sha512-rJxSqWIQXeeT2oLzSiQyqZPgDKSGH5sK7MUr8cOCBitqy3T0COlOMX4O7hhqF3cJ/5s0aX+MuNZBzF/D0QUcxA==
"@tauri-apps/cli-win32-x64-msvc@1.0.0-rc.13":
version "1.0.0-rc.13"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.0.0-rc.13.tgz#ed2feaf3b3a120c1460cae8941443563d14840bb"
integrity sha512-ifOTrJVQoBAQUYX+EVnE4XJ/FCMHs4FQ8qxGNszqkSxrU24mmT7La6tzj77352q80KnxRa05xjjLL6GGhmzXRg==
"@tauri-apps/cli@^1.0.0-rc.7":
version "1.0.0-rc.13"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli/-/cli-1.0.0-rc.13.tgz#e58127ebe24c6cc81c3258229219056199421500"
integrity sha512-q7i45Mi1SMv5XllNoX09QS4Q/fYVFwD6piVYmqMSrKY/T5RwedQhytiVH60TxC2xk6o0akVHa7BdYiyJvXNR8A==
optionalDependencies:
"@tauri-apps/cli-darwin-arm64" "1.0.0-rc.13"
"@tauri-apps/cli-darwin-x64" "1.0.0-rc.13"
"@tauri-apps/cli-linux-arm-gnueabihf" "1.0.0-rc.13"
"@tauri-apps/cli-linux-arm64-gnu" "1.0.0-rc.13"
"@tauri-apps/cli-linux-arm64-musl" "1.0.0-rc.13"
"@tauri-apps/cli-linux-x64-gnu" "1.0.0-rc.13"
"@tauri-apps/cli-linux-x64-musl" "1.0.0-rc.13"
"@tauri-apps/cli-win32-ia32-msvc" "1.0.0-rc.13"
"@tauri-apps/cli-win32-x64-msvc" "1.0.0-rc.13"
"@types/jest@^27.0.1":
version "27.4.1"
resolved "https://registry.npmmirror.com/@types/jest/-/jest-27.4.1.tgz"

Loading…
Cancel
Save