Compare commits
220 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ed8152f79 | ||
|
|
134095edc0 | ||
|
|
79ec62e33b | ||
|
|
3e7c42952b | ||
|
|
d776c2d3bc | ||
|
|
85d14a9489 | ||
|
|
6b304efc0e | ||
|
|
9fb0513703 | ||
|
|
7b96919d80 | ||
|
|
d6c3f542f3 | ||
|
|
1efac70cdb | ||
|
|
01c97c37f7 | ||
|
|
4fd262beae | ||
|
|
239115ead8 | ||
|
|
02b3e275d0 | ||
|
|
9810e55a15 | ||
|
|
03e4ad5db5 | ||
|
|
eb94e50f02 | ||
|
|
26444905cf | ||
|
|
d82b12ddaf | ||
|
|
b9a7970699 | ||
|
|
6f25e7baf3 | ||
| 513ed653e2 | |||
| 31cd9896b6 | |||
| 9c99508bdd | |||
|
|
f3e1ad74b5 | ||
|
|
ba0f9bfd98 | ||
|
|
d07881bc29 | ||
| cdcdac3531 | |||
| 0a19bb5518 | |||
| c7409fbf02 | |||
|
|
82d3824cae | ||
|
|
ba3c561c4c | ||
| 27fed91922 | |||
| 19585af99f | |||
| a752ef543c | |||
| 5614f678bd | |||
| b10eaf5133 | |||
| 4c2435b14c | |||
| 3d963e19e2 | |||
| 5148627d2d | |||
| da1e982ab5 | |||
|
|
5a12750f11 | ||
|
|
6139b4f722 | ||
|
|
9b85ae821a | ||
|
|
92e48bc613 | ||
|
|
0b6ec56511 | ||
|
|
6f3555a14f | ||
| 70a5b3db89 | |||
| 40bd9bb254 | |||
|
|
4473003a36 | ||
|
|
e5e6068337 | ||
|
|
1355634c22 | ||
|
|
2709af041b | ||
|
|
33c8712c72 | ||
|
|
26763c04e3 | ||
|
|
8c60a1f6c7 | ||
|
|
62b0e429b3 | ||
|
|
e1f1bea0e7 | ||
|
|
299ba0b93e | ||
|
|
c12c49477c | ||
|
|
b052754a30 | ||
|
|
aa1dc0896d | ||
|
|
8210ac24db | ||
|
|
cd3de96761 | ||
|
|
ce8ae4d26a | ||
|
|
50cfc23ad2 | ||
|
|
95539038c0 | ||
|
|
4b08a9ce84 | ||
|
|
6efdac7bab | ||
|
|
788cb2e6d4 | ||
|
|
dd8c05b344 | ||
|
|
e781e132ed | ||
|
|
862a6c8410 | ||
|
|
42535d0023 | ||
|
|
dd999cacf9 | ||
|
|
30d30bb8c6 | ||
|
|
f1c22dc9e6 | ||
| 14cf759ce1 | |||
| 19a19c1ff1 | |||
| 183d6d8b10 | |||
| d0cad61028 | |||
| efb34e0c5b | |||
|
|
8190e9f6b7 | ||
|
|
27435b57b7 | ||
|
|
0628882533 | ||
|
|
f68655eee6 | ||
|
|
d8491f0aba | ||
|
|
999f1f6a84 | ||
|
|
039acea0af | ||
|
|
d54de73e11 | ||
|
|
61d69159ea | ||
|
|
fa659d87ae | ||
|
|
ccc50a7dd0 | ||
|
|
d1a7ba8119 | ||
|
|
7c19a66cb5 | ||
|
|
90b72129a5 | ||
|
|
58bea0c09a | ||
|
|
50fe34e1c1 | ||
|
|
25c00d5072 | ||
|
|
ee32c8b83d | ||
|
|
12a193fdee | ||
|
|
ca55880beb | ||
|
|
ee9e399a81 | ||
|
|
ed9b0dd248 | ||
|
|
02edbdae8d | ||
|
|
5e75094c16 | ||
|
|
140317e2df | ||
|
|
8e2301eb34 | ||
|
|
c673da89cf | ||
|
|
005cf11b2a | ||
|
|
8195d633a1 | ||
|
|
4741a0bd93 | ||
|
|
f22c9df605 | ||
|
|
82cffdfe29 | ||
|
|
9da1a3bf25 | ||
|
|
2cb005e8ed | ||
|
|
374fdac477 | ||
|
|
595ababfde | ||
|
|
a62c359fd7 | ||
|
|
b45242dfeb | ||
|
|
a2763676b1 | ||
|
|
bd64ef06a9 | ||
|
|
abc1adb916 | ||
|
|
9ca1c43409 | ||
|
|
504836d165 | ||
|
|
e9962f1b74 | ||
|
|
1153313384 | ||
|
|
750d5c56ce | ||
|
|
c24ac78b91 | ||
|
|
569937c67f | ||
|
|
d6bfe1c2fb | ||
|
|
16da554a60 | ||
|
|
7f6635fb91 | ||
|
|
0605302db6 | ||
|
|
5f2fe5dcb2 | ||
|
|
452aefe3d0 | ||
|
|
97bf7fc390 | ||
|
|
08f2b2d9bc | ||
|
|
366ddb45ea | ||
|
|
09a9f14a29 | ||
|
|
e0afb55bb2 | ||
|
|
a469692358 | ||
|
|
bce7131d9f | ||
|
|
a53f7b718d | ||
|
|
75624ff0b7 | ||
|
|
743d232c38 | ||
|
|
1d0661ae40 | ||
|
|
69e72283dc | ||
|
|
a9d84c2db9 | ||
|
|
db3a2bf405 | ||
|
|
5e18d67747 | ||
|
|
8be47af097 | ||
|
|
4c24c4274c | ||
|
|
2a34ce6043 | ||
|
|
e8f94c911c | ||
|
|
f55b3bc609 | ||
|
|
d05d865b0d | ||
|
|
6e19671d06 | ||
|
|
f349dca0f7 | ||
|
|
58f00b4f8e | ||
|
|
d9ab1be2e7 | ||
|
|
4b77cd140d | ||
|
|
8d640be472 | ||
|
|
cc08e830d3 | ||
|
|
696f1bcbdb | ||
|
|
5c45ddb80b | ||
|
|
14de836089 | ||
|
|
1c4f804738 | ||
|
|
5fbe4d5dcf | ||
|
|
4963780a32 | ||
|
|
70ebaae3d2 | ||
|
|
9cd286fd92 | ||
|
|
f8ec441241 | ||
|
|
92a127e128 | ||
|
|
f654e0feda | ||
|
|
d44810e174 | ||
|
|
843cdc94d4 | ||
|
|
dd1d6ce2a6 | ||
|
|
1df0172acc | ||
|
|
1a3d79a605 | ||
|
|
0e55698a47 | ||
|
|
6eeb5a57cd | ||
|
|
6988e99717 | ||
|
|
754fd11ad2 | ||
|
|
4bd9d101c7 | ||
|
|
eee58c8da8 | ||
|
|
c281b4a30d | ||
|
|
74a746bc47 | ||
|
|
9f337df9de | ||
|
|
45ffdc37fb | ||
|
|
6765eff93f | ||
|
|
fab208c121 | ||
|
|
e45e8c7572 | ||
|
|
e9540d0971 | ||
|
|
6d2b68a202 | ||
|
|
144e2ffb25 | ||
|
|
0a1c3c436e | ||
|
|
8c6be6f487 | ||
|
|
915d474fea | ||
|
|
0cfaa799f5 | ||
|
|
36a34891db | ||
|
|
4862dcd1d8 | ||
|
|
9461ad77ed | ||
|
|
33c45920e3 | ||
|
|
2b51cc5f7c | ||
|
|
167f90b250 | ||
|
|
5e885af295 | ||
|
|
b219123ded | ||
|
|
d3062a0240 | ||
|
|
f9bdc0f707 | ||
|
|
9df7bd891e | ||
|
|
6b0d2359c5 | ||
|
|
5b1f4066f3 | ||
|
|
037541abc8 | ||
|
|
dfd52063aa | ||
|
|
46448c9727 | ||
|
|
05d88a89f4 | ||
|
|
41dd5e4db9 | ||
|
|
72d021a179 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.idea/
|
||||
36
.gitlab-ci.yml
Normal file
36
.gitlab-ci.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
# This file is a template, and might need editing before it works on your project.
|
||||
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
|
||||
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
|
||||
#
|
||||
# To contribute improvements to CI/CD templates, please follow the Development guide at:
|
||||
# https://docs.gitlab.com/ee/development/cicd/templates.html
|
||||
# This specific template is located at:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Go.gitlab-ci.yml
|
||||
|
||||
image: golang:latest
|
||||
|
||||
stages:
|
||||
- test
|
||||
# - build
|
||||
# - deploy
|
||||
|
||||
format:
|
||||
stage: test
|
||||
script:
|
||||
- go fmt $(go list ./... | grep -v /vendor/)
|
||||
- go vet $(go list ./... | grep -v /vendor/)
|
||||
- go test -race $(go list ./... | grep -v /vendor/)
|
||||
|
||||
#compile:
|
||||
# stage: build
|
||||
# script:
|
||||
# - mkdir -p mybinaries
|
||||
# - go build -o mybinaries main.go
|
||||
# artifacts:
|
||||
# paths:
|
||||
# - build
|
||||
#
|
||||
#deploy:
|
||||
# stage: deploy
|
||||
# script: echo "Define your deployment script!"
|
||||
# environment: production
|
||||
8
.idea/.gitignore
generated
vendored
8
.idea/.gitignore
generated
vendored
@@ -1,8 +0,0 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
6
.idea/goframehelperCache.xml
generated
6
.idea/goframehelperCache.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="com.github.oldmegit.goframehelper.ui.goframehelperCache">
|
||||
<option name="gf" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/utility-go.iml" filepath="$PROJECT_DIR$/.idea/utility-go.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
9
.idea/utility-go.iml
generated
9
.idea/utility-go.iml
generated
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="Go" enabled="true" />
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
419
README.md
Normal file
419
README.md
Normal file
@@ -0,0 +1,419 @@
|
||||
# utility_go
|
||||
|
||||
[](https://golang.org)
|
||||
[](LICENSE)
|
||||
[](https://github.com/ayflying/utility_go/stargazers)
|
||||
|
||||
一个功能丰富的Go语言工具类库,提供支付集成、缓存管理、排名算法、数据库操作、系统管理等核心功能模块,适用于各类Go项目开发。
|
||||
|
||||
## ✨ 核心特性
|
||||
|
||||
- **🔧 多模块集成**: 支付、缓存、排名、数据库、系统管理等完整解决方案
|
||||
- **⚡ 高性能**: 基于Redis的高性能排名算法和缓存管理
|
||||
- **📱 支付支持**: 集成Apple Pay、Google Play Store、支付宝、微信支付等主流支付平台
|
||||
- **🛠️ CLI工具**: 提供代码生成器,快速创建模块文件
|
||||
- **📊 监控告警**: 集成Prometheus监控和系统日志管理
|
||||
- **🌐 多存储支持**: 支持S3对象存储、Elasticsearch搜索引擎
|
||||
|
||||
## 📦 安装
|
||||
|
||||
```bash
|
||||
go get github.com/ayflying/utility_go
|
||||
```
|
||||
|
||||
## 🏗️ 项目结构
|
||||
|
||||
```
|
||||
utility_go/
|
||||
├── api/ # API接口定义
|
||||
│ ├── admin/ # 管理后台API
|
||||
│ ├── callback/ # 回调接口
|
||||
│ ├── system/ # 系统API
|
||||
│ └── pkg/ # 包相关API
|
||||
├── cmd/ # CLI命令工具
|
||||
│ ├── make.go # 代码生成器
|
||||
│ ├── load.go # 配置加载
|
||||
│ ├── update.go # 更新工具
|
||||
│ └── middleware.go # 中间件工具
|
||||
├── controller/ # 控制器层
|
||||
│ └── callback/ # 回调控制器
|
||||
├── service/ # 服务层
|
||||
│ ├── casdoor.go # 认证服务
|
||||
│ ├── game_act.go # 游戏活动服务
|
||||
│ ├── game_kv.go # 键值存储服务
|
||||
│ ├── ip_2_region.go # IP地理位置服务
|
||||
│ ├── log_data.go # 日志数据服务
|
||||
│ ├── os.go # 操作系统服务
|
||||
│ ├── system_cron.go # 定时任务服务
|
||||
│ └── system_log.go # 系统日志服务
|
||||
├── internal/ # 内部核心逻辑
|
||||
│ ├── boot/ # 启动初始化
|
||||
│ ├── game/ # 游戏逻辑
|
||||
│ ├── logic/ # 业务逻辑
|
||||
│ │ ├── casdoor/ # 认证逻辑
|
||||
│ │ ├── gameAct/ # 游戏活动
|
||||
│ │ ├── gameKv/ # 游戏键值存储
|
||||
│ │ ├── ip2region/ # IP区域查询
|
||||
│ │ ├── logData/ # 日志处理
|
||||
│ │ ├── os/ # 系统操作
|
||||
│ │ ├── systemCron/ # 定时任务
|
||||
│ │ └── systemLog/ # 系统日志
|
||||
│ └── model/ # 数据模型
|
||||
│ ├── do/ # 数据对象
|
||||
│ └── entity/ # 实体定义
|
||||
├── package/ # 功能包
|
||||
│ ├── aycache/ # 缓存管理
|
||||
│ ├── excel/ # Excel处理
|
||||
│ ├── gamelog/ # 游戏日志
|
||||
│ ├── pay/ # 支付集成
|
||||
│ │ ├── alipay/ # 支付宝
|
||||
│ │ ├── apple/ # Apple Pay
|
||||
│ │ ├── google/ # Google Play
|
||||
│ │ ├── wechat/ # 微信支付
|
||||
│ │ ├── playstore/ # Play Store
|
||||
│ │ └── ... # 其他支付平台
|
||||
│ ├── rank/ # 排名算法
|
||||
│ └── s3/ # S3存储
|
||||
├── pkg/ # 公共包
|
||||
│ ├── aycache/ # 缓存包
|
||||
│ ├── config/ # 配置包
|
||||
│ ├── elasticsearch/ # ES包
|
||||
│ ├── notice/ # 通知包
|
||||
│ ├── rank/ # 排名包
|
||||
│ └── s3/ # S3包
|
||||
├── tools/ # 工具函数
|
||||
│ ├── random.go # 随机数
|
||||
│ ├── redis.go # Redis操作
|
||||
│ ├── time.go # 时间处理
|
||||
│ └── tools.go # 通用工具
|
||||
├── utility.go # 主入口
|
||||
├── go.mod # 模块定义
|
||||
└── README.md # 说明文档
|
||||
```
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 1. 初始化项目
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/ayflying/utility_go"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
g.Log().Info(nil, "项目启动成功")
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 使用CLI工具生成代码
|
||||
|
||||
```bash
|
||||
# 创建活动模块
|
||||
go run main.go make -m act -i 1
|
||||
|
||||
# 创建逻辑模块
|
||||
go run main.go make -m logic -n test
|
||||
|
||||
# 创建配置文件
|
||||
go run main.go make -m config -n test
|
||||
|
||||
# 创建Socket模块
|
||||
go run main.go make -m socket -n test
|
||||
```
|
||||
|
||||
## 📚 核心模块详解
|
||||
|
||||
### 🔐 支付模块 (package/pay)
|
||||
|
||||
支持多种支付平台集成:
|
||||
|
||||
#### Google Play Store
|
||||
```go
|
||||
import "github.com/ayflying/utility_go/package/pay/playstore"
|
||||
|
||||
// 创建客户端
|
||||
client, err := playstore.New(jsonKey)
|
||||
|
||||
// 验证签名
|
||||
isValid, err := playstore.VerifySignature(publicKey, receipt, signature)
|
||||
```
|
||||
|
||||
#### Apple Pay
|
||||
```go
|
||||
import "github.com/ayflying/utility_go/package/pay/apple"
|
||||
|
||||
// 处理Apple支付验证
|
||||
```
|
||||
|
||||
#### 支付宝/微信支付
|
||||
```go
|
||||
import (
|
||||
"github.com/ayflying/utility_go/package/pay/alipay"
|
||||
"github.com/ayflying/utility_go/package/pay/wechat"
|
||||
)
|
||||
```
|
||||
|
||||
### 🏆 排名模块 (package/rank)
|
||||
|
||||
基于Redis的高性能排行榜实现:
|
||||
|
||||
```go
|
||||
import "github.com/ayflying/utility_go/pkg/rank"
|
||||
|
||||
// 创建排行榜
|
||||
rankMod := rank.New()
|
||||
leaderboard := rankMod.CreateF64CountRank("season_1")
|
||||
|
||||
// 增加分数
|
||||
curScore, err := leaderboard.IncrScore(userID, 100)
|
||||
|
||||
// 设置分数
|
||||
err := leaderboard.SetScore(userID, 500)
|
||||
|
||||
// 获取排名信息
|
||||
rankInfo, err := leaderboard.GetRankInfosNotTs(0, 10)
|
||||
```
|
||||
|
||||
### 💾 缓存模块 (package/aycache)
|
||||
|
||||
```go
|
||||
import "github.com/ayflying/utility_go/package/aycache"
|
||||
|
||||
// 使用缓存
|
||||
cache := aycache.New()
|
||||
```
|
||||
|
||||
### 📊 数据库操作
|
||||
|
||||
#### Elasticsearch
|
||||
```go
|
||||
import "github.com/ayflying/utility_go/package/elasticsearch"
|
||||
|
||||
// ES操作
|
||||
```
|
||||
|
||||
#### MySQL (基于GoFrame)
|
||||
```go
|
||||
import "github.com/gogf/gf/v2/database/gdb"
|
||||
```
|
||||
|
||||
### 🔄 定时任务 (systemCron)
|
||||
|
||||
```go
|
||||
import "github.com/ayflying/utility_go/service"
|
||||
|
||||
// 添加定时任务
|
||||
service.SystemCron().AddCronV2(v1.CronType_HOUR, func(ctx context.Context) error {
|
||||
// 执行任务
|
||||
return nil
|
||||
}, true)
|
||||
```
|
||||
|
||||
### 📝 日志管理 (systemLog)
|
||||
|
||||
```go
|
||||
import "github.com/ayflying/utility_go/service"
|
||||
|
||||
// 记录日志
|
||||
service.SystemLog().Info("操作成功")
|
||||
service.SystemLog().Error("操作失败: %v", err)
|
||||
```
|
||||
|
||||
### 🌐 IP地理位置查询 (ip2region)
|
||||
|
||||
```go
|
||||
import "github.com/ayflying/utility_go/service"
|
||||
|
||||
// 查询IP位置
|
||||
ipInfo, err := service.Ip2Region().Search("192.168.1.1")
|
||||
```
|
||||
|
||||
### 📁 S3存储 (s3)
|
||||
|
||||
```go
|
||||
import "github.com/ayflying/utility_go/package/s3"
|
||||
|
||||
// 列出存储桶
|
||||
buckets, err := s3.ListBuckets()
|
||||
|
||||
// 上传文件
|
||||
err := s3.UploadFile("bucket-name", "file-key", fileData)
|
||||
```
|
||||
|
||||
### 📑 Excel处理 (excel)
|
||||
|
||||
```go
|
||||
import "github.com/ayflying/utility_go/package/excel"
|
||||
|
||||
// 读取Excel
|
||||
data, err := excel.Read("file.xlsx")
|
||||
|
||||
// 导出Excel
|
||||
err := excel.Export(data, "output.xlsx")
|
||||
```
|
||||
|
||||
## 🛠️ 配置管理
|
||||
|
||||
项目使用GoFrame框架的配置管理:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/ayflying/utility_go/config"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// 获取配置
|
||||
cfg := config.Cfg{}
|
||||
dbConfig := g.Cfg().Get("database")
|
||||
```
|
||||
|
||||
## 🔧 工具函数
|
||||
|
||||
### 时间处理 (tools/time.go)
|
||||
```go
|
||||
import "github.com/ayflying/utility_go/tools"
|
||||
|
||||
// 获取本周开始时间
|
||||
weekStart := tools.GetWeekStart()
|
||||
|
||||
// 计算天数差
|
||||
days := tools.DiffDays(startTime, endTime)
|
||||
```
|
||||
|
||||
### Redis操作 (tools/redis.go)
|
||||
```go
|
||||
// 批量获取数据
|
||||
data, err := tools.ScanRedis(pattern)
|
||||
```
|
||||
|
||||
### 通用工具 (tools/tools.go)
|
||||
```go
|
||||
// 字符串转道具类型
|
||||
items := tools.Tools.Spilt2Item("1|10|2|20")
|
||||
|
||||
// 切片转道具类型
|
||||
items := tools.Tools.Slice2Item([]int64{1, 10, 2, 20})
|
||||
|
||||
// 道具格式转Map
|
||||
itemMap := tools.Tools.Items2Map(items)
|
||||
```
|
||||
|
||||
## 🎯 使用示例
|
||||
|
||||
### 完整的支付验证流程
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ayflying/utility_go/package/pay/playstore"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Google Play Store应用内购买验证
|
||||
purchaseData := "purchase_data_string"
|
||||
signature := "signature_string"
|
||||
publicKey := "base64_encoded_public_key"
|
||||
|
||||
isValid, err := playstore.VerifySignature(publicKey, []byte(purchaseData), signature)
|
||||
if err != nil {
|
||||
fmt.Println("验证失败:", err)
|
||||
return
|
||||
}
|
||||
|
||||
if isValid {
|
||||
fmt.Println("支付验证成功")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 排行榜使用示例
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ayflying/utility_go/pkg/rank"
|
||||
)
|
||||
|
||||
func main() {
|
||||
rankMod := rank.New()
|
||||
leaderboard := rankMod.CreateF64CountRank("game_season_1")
|
||||
|
||||
// 用户得分
|
||||
score, err := leaderboard.IncrScore(1001, 50)
|
||||
if err != nil {
|
||||
fmt.Println("更新分数失败:", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("当前分数: %.0f\n", score)
|
||||
|
||||
// 获取前10名
|
||||
top10, err := leaderboard.GetRankInfosNotTs(0, 9)
|
||||
if err != nil {
|
||||
fmt.Println("获取排名失败:", err)
|
||||
return
|
||||
}
|
||||
|
||||
for i, info := range top10 {
|
||||
fmt.Printf("第%d名: 用户%d - 分数%d\n", i+1, info.Id, info.Score)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## ⚙️ 开发指南
|
||||
|
||||
### 代码规范
|
||||
- 使用GoFrame框架的最佳实践
|
||||
- 遵循Go语言命名规范
|
||||
- 添加必要的注释和文档
|
||||
- 使用错误处理和日志记录
|
||||
|
||||
### 项目启动流程
|
||||
1. 配置文件加载
|
||||
2. 数据库连接初始化
|
||||
3. 缓存系统初始化
|
||||
4. 定时任务注册
|
||||
5. 服务启动监听
|
||||
|
||||
### 注意事项
|
||||
- ⚠️ **自动生成文件**: 使用CLI工具生成的文件包含 `// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.` 注释,请勿手动修改
|
||||
- 🔒 **版本兼容性**: 建议使用Go 1.24+版本
|
||||
- 📦 **依赖管理**: 使用go mod管理依赖
|
||||
|
||||
## 🔄 更新维护
|
||||
|
||||
- **定期更新**: 修复已知问题,添加新功能
|
||||
- **性能优化**: 持续优化性能表现
|
||||
- **安全补丁**: 及时修复安全漏洞
|
||||
|
||||
## 📄 许可证
|
||||
|
||||
本项目采用 [MIT License](LICENSE) 许可证。
|
||||
|
||||
## 🤝 贡献指南
|
||||
|
||||
欢迎提交Issue和Pull Request来贡献代码!
|
||||
|
||||
1. Fork本仓库
|
||||
2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
|
||||
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
|
||||
4. 推送到分支 (`git push origin feature/AmazingFeature`)
|
||||
5. 开启Pull Request
|
||||
|
||||
## 📞 联系方式
|
||||
|
||||
- **GitHub**: https://github.com/ayflying/utility_go
|
||||
- **Gitee**: https://gitea.adesk.com/public_project/utility_go
|
||||
|
||||
## 🙏 致谢
|
||||
|
||||
感谢所有贡献者和开源社区的支持!
|
||||
|
||||
---
|
||||
|
||||
**utility_go** © 2025 - Made with ❤️ by [ayflying]
|
||||
12
api/admin/v1/log.go
Normal file
12
api/admin/v1/log.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"github.com/ayflying/utility_go/internal/model/entity"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
type SystemLog struct {
|
||||
entity.SystemLog
|
||||
Data g.Map `json:"data" dc:"操作数据"`
|
||||
//Post g.Map `json:"post" dc:"提交数据"`
|
||||
}
|
||||
16
api/callback/callback.go
Normal file
16
api/callback/callback.go
Normal file
@@ -0,0 +1,16 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package callback
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ayflying/utility_go/api/callback/v1"
|
||||
)
|
||||
|
||||
type ICallbackV1 interface {
|
||||
Ip(ctx context.Context, req *v1.IpReq) (res *v1.IpRes, err error)
|
||||
Robots(ctx context.Context, req *v1.RobotsReq) (res *v1.RobotsRes, err error)
|
||||
}
|
||||
20
api/callback/v1/ip.go
Normal file
20
api/callback/v1/ip.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package v1
|
||||
|
||||
import "github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
type IpReq struct {
|
||||
g.Meta `path:"/callback/ip/{ip}" tags:"回调响应" method:"get" summary:"获取ip"`
|
||||
Ip string `json:"ip" dc:"ip"`
|
||||
}
|
||||
type IpRes struct {
|
||||
g.Meta `mime:"application/json" example:"string"`
|
||||
Address []string `json:"address" dc:"地区名"`
|
||||
}
|
||||
|
||||
type Ip struct {
|
||||
Country string `json:"country" dc:"国家"` //国家
|
||||
Region string `json:"region" dc:"地区"` //地区
|
||||
Province string `json:"province" dc:"省份"` //省份
|
||||
City string `json:"city" dc:"城市"` //城市
|
||||
District string `json:"district" dc:"区县"` //区县
|
||||
}
|
||||
9
api/callback/v1/robots.go
Normal file
9
api/callback/v1/robots.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package v1
|
||||
|
||||
import "github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
type RobotsReq struct {
|
||||
g.Meta `path:"/robots.txt" tags:"回调响应" method:"get" summary:"禁止爬虫"`
|
||||
}
|
||||
type RobotsRes struct {
|
||||
}
|
||||
237
api/pkg/v1/pkg.pb.go
Normal file
237
api/pkg/v1/pkg.pb.go
Normal file
@@ -0,0 +1,237 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.20.0
|
||||
// source: pkg/v1/pkg.proto
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// 定义 NoticeType 枚举
|
||||
type NoticeType int32
|
||||
|
||||
const (
|
||||
NoticeType_DINGTALK NoticeType = 0
|
||||
NoticeType_WECHAT NoticeType = 1
|
||||
NoticeType_EMAIL NoticeType = 2
|
||||
NoticeType_SMS NoticeType = 3
|
||||
NoticeType_VOICE NoticeType = 4
|
||||
)
|
||||
|
||||
// Enum value maps for NoticeType.
|
||||
var (
|
||||
NoticeType_name = map[int32]string{
|
||||
0: "DINGTALK",
|
||||
1: "WECHAT",
|
||||
2: "EMAIL",
|
||||
3: "SMS",
|
||||
4: "VOICE",
|
||||
}
|
||||
NoticeType_value = map[string]int32{
|
||||
"DINGTALK": 0,
|
||||
"WECHAT": 1,
|
||||
"EMAIL": 2,
|
||||
"SMS": 3,
|
||||
"VOICE": 4,
|
||||
}
|
||||
)
|
||||
|
||||
func (x NoticeType) Enum() *NoticeType {
|
||||
p := new(NoticeType)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x NoticeType) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (NoticeType) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_pkg_v1_pkg_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (NoticeType) Type() protoreflect.EnumType {
|
||||
return &file_pkg_v1_pkg_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x NoticeType) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use NoticeType.Descriptor instead.
|
||||
func (NoticeType) EnumDescriptor() ([]byte, []int) {
|
||||
return file_pkg_v1_pkg_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
// 排行榜数据
|
||||
type RankData struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Score int64 `protobuf:"varint,2,opt,name=score,proto3" json:"score,omitempty"`
|
||||
Rank int32 `protobuf:"varint,3,opt,name=rank,proto3" json:"rank,omitempty"`
|
||||
UpdateTs int64 `protobuf:"varint,4,opt,name=update_ts,json=updateTs,proto3" json:"update_ts,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RankData) Reset() {
|
||||
*x = RankData{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_pkg_v1_pkg_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *RankData) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RankData) ProtoMessage() {}
|
||||
|
||||
func (x *RankData) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_pkg_v1_pkg_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use RankData.ProtoReflect.Descriptor instead.
|
||||
func (*RankData) Descriptor() ([]byte, []int) {
|
||||
return file_pkg_v1_pkg_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *RankData) GetId() int64 {
|
||||
if x != nil {
|
||||
return x.Id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *RankData) GetScore() int64 {
|
||||
if x != nil {
|
||||
return x.Score
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *RankData) GetRank() int32 {
|
||||
if x != nil {
|
||||
return x.Rank
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *RankData) GetUpdateTs() int64 {
|
||||
if x != nil {
|
||||
return x.UpdateTs
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_pkg_v1_pkg_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_pkg_v1_pkg_proto_rawDesc = []byte{
|
||||
0x0a, 0x10, 0x70, 0x6b, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x6b, 0x67, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x12, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x22, 0x61, 0x0a, 0x08, 0x52,
|
||||
0x61, 0x6e, 0x6b, 0x44, 0x61, 0x74, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x12, 0x0a,
|
||||
0x04, 0x72, 0x61, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x72, 0x61, 0x6e,
|
||||
0x6b, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x73, 0x18, 0x04,
|
||||
0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x73, 0x2a, 0x45,
|
||||
0x0a, 0x0a, 0x4e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08,
|
||||
0x44, 0x49, 0x4e, 0x47, 0x54, 0x41, 0x4c, 0x4b, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x57, 0x45,
|
||||
0x43, 0x48, 0x41, 0x54, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x4d, 0x41, 0x49, 0x4c, 0x10,
|
||||
0x02, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x4d, 0x53, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x56, 0x4f,
|
||||
0x49, 0x43, 0x45, 0x10, 0x04, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x79, 0x66, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x2f, 0x75, 0x74, 0x69,
|
||||
0x6c, 0x69, 0x74, 0x79, 0x5f, 0x67, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6b, 0x67, 0x2f,
|
||||
0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_pkg_v1_pkg_proto_rawDescOnce sync.Once
|
||||
file_pkg_v1_pkg_proto_rawDescData = file_pkg_v1_pkg_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_pkg_v1_pkg_proto_rawDescGZIP() []byte {
|
||||
file_pkg_v1_pkg_proto_rawDescOnce.Do(func() {
|
||||
file_pkg_v1_pkg_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_v1_pkg_proto_rawDescData)
|
||||
})
|
||||
return file_pkg_v1_pkg_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_pkg_v1_pkg_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_pkg_v1_pkg_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||
var file_pkg_v1_pkg_proto_goTypes = []interface{}{
|
||||
(NoticeType)(0), // 0: package.NoticeType
|
||||
(*RankData)(nil), // 1: package.RankData
|
||||
}
|
||||
var file_pkg_v1_pkg_proto_depIdxs = []int32{
|
||||
0, // [0:0] is the sub-list for method output_type
|
||||
0, // [0:0] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_pkg_v1_pkg_proto_init() }
|
||||
func file_pkg_v1_pkg_proto_init() {
|
||||
if File_pkg_v1_pkg_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_pkg_v1_pkg_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*RankData); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_pkg_v1_pkg_proto_rawDesc,
|
||||
NumEnums: 1,
|
||||
NumMessages: 1,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_pkg_v1_pkg_proto_goTypes,
|
||||
DependencyIndexes: file_pkg_v1_pkg_proto_depIdxs,
|
||||
EnumInfos: file_pkg_v1_pkg_proto_enumTypes,
|
||||
MessageInfos: file_pkg_v1_pkg_proto_msgTypes,
|
||||
}.Build()
|
||||
File_pkg_v1_pkg_proto = out.File
|
||||
file_pkg_v1_pkg_proto_rawDesc = nil
|
||||
file_pkg_v1_pkg_proto_goTypes = nil
|
||||
file_pkg_v1_pkg_proto_depIdxs = nil
|
||||
}
|
||||
180
api/system/v1/cron.pb.go
Normal file
180
api/system/v1/cron.pb.go
Normal file
@@ -0,0 +1,180 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.20.0
|
||||
// source: system/v1/cron.proto
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// 定义 CronType 计划任务 枚举
|
||||
type CronType int32
|
||||
|
||||
const (
|
||||
CronType_UNKNOWN CronType = 0 // 未知类型
|
||||
CronType_SECOND CronType = 1 // 每秒触发一次
|
||||
CronType_MINUTE CronType = 2 // 每分钟触发一次
|
||||
CronType_HOUR CronType = 3 // 每小时触发一次
|
||||
CronType_DAILY CronType = 4 // 每天触发一次
|
||||
CronType_WEEK CronType = 5 // 每周触发一次
|
||||
CronType_MONTH CronType = 6 // 每月触发一次
|
||||
CronType_YEAR CronType = 7 // 每年触发一次
|
||||
CronType_MONDAY CronType = 8 // 每周一触发一次
|
||||
CronType_TUESDAY CronType = 9 // 每周二触发一次
|
||||
CronType_WEDNESDAY CronType = 10 // 每周三触发一次
|
||||
CronType_THURSDAY CronType = 11 // 每周四触发一次
|
||||
CronType_FRIDAY CronType = 12 // 每周五触发一次
|
||||
CronType_SATURDAY CronType = 13 // 每周六触发一次
|
||||
CronType_SUNDAY CronType = 14 // 每周日触发一次
|
||||
)
|
||||
|
||||
// Enum value maps for CronType.
|
||||
var (
|
||||
CronType_name = map[int32]string{
|
||||
0: "UNKNOWN",
|
||||
1: "SECOND",
|
||||
2: "MINUTE",
|
||||
3: "HOUR",
|
||||
4: "DAILY",
|
||||
5: "WEEK",
|
||||
6: "MONTH",
|
||||
7: "YEAR",
|
||||
8: "MONDAY",
|
||||
9: "TUESDAY",
|
||||
10: "WEDNESDAY",
|
||||
11: "THURSDAY",
|
||||
12: "FRIDAY",
|
||||
13: "SATURDAY",
|
||||
14: "SUNDAY",
|
||||
}
|
||||
CronType_value = map[string]int32{
|
||||
"UNKNOWN": 0,
|
||||
"SECOND": 1,
|
||||
"MINUTE": 2,
|
||||
"HOUR": 3,
|
||||
"DAILY": 4,
|
||||
"WEEK": 5,
|
||||
"MONTH": 6,
|
||||
"YEAR": 7,
|
||||
"MONDAY": 8,
|
||||
"TUESDAY": 9,
|
||||
"WEDNESDAY": 10,
|
||||
"THURSDAY": 11,
|
||||
"FRIDAY": 12,
|
||||
"SATURDAY": 13,
|
||||
"SUNDAY": 14,
|
||||
}
|
||||
)
|
||||
|
||||
func (x CronType) Enum() *CronType {
|
||||
p := new(CronType)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x CronType) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (CronType) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_system_v1_cron_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (CronType) Type() protoreflect.EnumType {
|
||||
return &file_system_v1_cron_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x CronType) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use CronType.Descriptor instead.
|
||||
func (CronType) EnumDescriptor() ([]byte, []int) {
|
||||
return file_system_v1_cron_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
var File_system_v1_cron_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_system_v1_cron_proto_rawDesc = []byte{
|
||||
0x0a, 0x14, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x72, 0x6f, 0x6e,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2a, 0xbf,
|
||||
0x01, 0x0a, 0x08, 0x43, 0x72, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55,
|
||||
0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x45, 0x43, 0x4f,
|
||||
0x4e, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x49, 0x4e, 0x55, 0x54, 0x45, 0x10, 0x02,
|
||||
0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x55, 0x52, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x41,
|
||||
0x49, 0x4c, 0x59, 0x10, 0x04, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x45, 0x45, 0x4b, 0x10, 0x05, 0x12,
|
||||
0x09, 0x0a, 0x05, 0x4d, 0x4f, 0x4e, 0x54, 0x48, 0x10, 0x06, 0x12, 0x08, 0x0a, 0x04, 0x59, 0x45,
|
||||
0x41, 0x52, 0x10, 0x07, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x4f, 0x4e, 0x44, 0x41, 0x59, 0x10, 0x08,
|
||||
0x12, 0x0b, 0x0a, 0x07, 0x54, 0x55, 0x45, 0x53, 0x44, 0x41, 0x59, 0x10, 0x09, 0x12, 0x0d, 0x0a,
|
||||
0x09, 0x57, 0x45, 0x44, 0x4e, 0x45, 0x53, 0x44, 0x41, 0x59, 0x10, 0x0a, 0x12, 0x0c, 0x0a, 0x08,
|
||||
0x54, 0x48, 0x55, 0x52, 0x53, 0x44, 0x41, 0x59, 0x10, 0x0b, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x52,
|
||||
0x49, 0x44, 0x41, 0x59, 0x10, 0x0c, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x41, 0x54, 0x55, 0x52, 0x44,
|
||||
0x41, 0x59, 0x10, 0x0d, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x55, 0x4e, 0x44, 0x41, 0x59, 0x10, 0x0e,
|
||||
0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61,
|
||||
0x79, 0x66, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x2f, 0x75, 0x74, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x5f,
|
||||
0x67, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2f, 0x76, 0x31,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_system_v1_cron_proto_rawDescOnce sync.Once
|
||||
file_system_v1_cron_proto_rawDescData = file_system_v1_cron_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_system_v1_cron_proto_rawDescGZIP() []byte {
|
||||
file_system_v1_cron_proto_rawDescOnce.Do(func() {
|
||||
file_system_v1_cron_proto_rawDescData = protoimpl.X.CompressGZIP(file_system_v1_cron_proto_rawDescData)
|
||||
})
|
||||
return file_system_v1_cron_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_system_v1_cron_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_system_v1_cron_proto_goTypes = []interface{}{
|
||||
(CronType)(0), // 0: system.CronType
|
||||
}
|
||||
var file_system_v1_cron_proto_depIdxs = []int32{
|
||||
0, // [0:0] is the sub-list for method output_type
|
||||
0, // [0:0] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_system_v1_cron_proto_init() }
|
||||
func file_system_v1_cron_proto_init() {
|
||||
if File_system_v1_cron_proto != nil {
|
||||
return
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_system_v1_cron_proto_rawDesc,
|
||||
NumEnums: 1,
|
||||
NumMessages: 0,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_system_v1_cron_proto_goTypes,
|
||||
DependencyIndexes: file_system_v1_cron_proto_depIdxs,
|
||||
EnumInfos: file_system_v1_cron_proto_enumTypes,
|
||||
}.Build()
|
||||
File_system_v1_cron_proto = out.File
|
||||
file_system_v1_cron_proto_rawDesc = nil
|
||||
file_system_v1_cron_proto_goTypes = nil
|
||||
file_system_v1_cron_proto_depIdxs = nil
|
||||
}
|
||||
15
aycache/aycache.go
Normal file
15
aycache/aycache.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package aycache
|
||||
|
||||
import (
|
||||
"github.com/ayflying/utility_go/pkg"
|
||||
"github.com/gogf/gf/v2/os/gcache"
|
||||
)
|
||||
|
||||
type Mod struct {
|
||||
client *gcache.Cache
|
||||
}
|
||||
|
||||
// Deprecated:弃用,改用 pkg.Cache()
|
||||
func New(_name ...string) gcache.Adapter {
|
||||
return pkg.Cache(_name...)
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package aycache
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/os/gcache"
|
||||
)
|
||||
|
||||
type Mod struct {
|
||||
client *gcache.Cache
|
||||
}
|
||||
|
||||
//func NewV1(_name ...string) *cache.Mod {
|
||||
// return pgk.Cache
|
||||
//}
|
||||
|
||||
func New(_name ...string) gcache.Adapter {
|
||||
|
||||
var cacheAdapterObj gcache.Adapter
|
||||
var name = "cache"
|
||||
if len(_name) > 0 {
|
||||
name = _name[0]
|
||||
}
|
||||
switch name {
|
||||
case "cache":
|
||||
cacheAdapterObj = NewAdapterMemory()
|
||||
case "redis":
|
||||
cacheAdapterObj = NewAdapterRedis()
|
||||
}
|
||||
|
||||
//var client = gcache.New()
|
||||
//client.SetAdapter(cacheAdapterObj)
|
||||
return cacheAdapterObj
|
||||
}
|
||||
118
aycache/file.go
118
aycache/file.go
@@ -1,118 +0,0 @@
|
||||
package aycache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/container/gvar"
|
||||
"github.com/gogf/gf/v2/os/gcache"
|
||||
"time"
|
||||
)
|
||||
|
||||
type AdapterFile struct {
|
||||
FilePath string
|
||||
}
|
||||
|
||||
func (a AdapterFile) Set(ctx context.Context, key interface{}, value interface{}, duration time.Duration) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) SetMap(ctx context.Context, data map[interface{}]interface{}, duration time.Duration) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) SetIfNotExist(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (ok bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) SetIfNotExistFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) SetIfNotExistFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Get(ctx context.Context, key interface{}) (*gvar.Var, error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) GetOrSet(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (result *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) GetOrSetFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) GetOrSetFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Contains(ctx context.Context, key interface{}) (bool, error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Size(ctx context.Context) (size int, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Data(ctx context.Context) (data map[interface{}]interface{}, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Keys(ctx context.Context) (keys []interface{}, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Values(ctx context.Context) (values []interface{}, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Update(ctx context.Context, key interface{}, value interface{}) (oldValue *gvar.Var, exist bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) UpdateExpire(ctx context.Context, key interface{}, duration time.Duration) (oldDuration time.Duration, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) GetExpire(ctx context.Context, key interface{}) (time.Duration, error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Remove(ctx context.Context, keys ...interface{}) (lastValue *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Clear(ctx context.Context) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Close(ctx context.Context) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func NewAdapterFile(filePath string) gcache.Adapter {
|
||||
return &AdapterFile{
|
||||
FilePath: filePath,
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package aycache
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcache"
|
||||
)
|
||||
|
||||
var adapterRedisClient gcache.Adapter
|
||||
var adapterRedisCache = gcache.New()
|
||||
|
||||
func NewAdapterRedis() gcache.Adapter {
|
||||
|
||||
if adapterRedisClient == nil {
|
||||
adapterRedisClient = gcache.NewAdapterRedis(g.Redis("cache"))
|
||||
adapterRedisCache.SetAdapter(adapterRedisClient)
|
||||
}
|
||||
return adapterRedisCache
|
||||
}
|
||||
32
cmd/load.go
Normal file
32
cmd/load.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/ayflying/utility_go/controller/callback"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
func Load(s *ghttp.Server) {
|
||||
|
||||
//开启prometheus监控
|
||||
s.Group("/metrics", func(group *ghttp.RouterGroup) {
|
||||
group.Bind(
|
||||
ghttp.WrapH(promhttp.Handler()),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// 注册游客方法
|
||||
func RegistrationAnonymous(group *ghttp.RouterGroup) (res []interface{}) {
|
||||
group.Bind(
|
||||
callback.NewV1(),
|
||||
)
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// 注册用户方法
|
||||
func RegistrationUser(group *ghttp.RouterGroup) (res []interface{}) {
|
||||
group.Bind()
|
||||
return
|
||||
}
|
||||
147
cmd/make.go
Normal file
147
cmd/make.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"io/fs"
|
||||
)
|
||||
|
||||
//go:embed make/*
|
||||
var ConfigFiles embed.FS
|
||||
|
||||
var (
|
||||
Make = gcmd.Command{
|
||||
Name: "make",
|
||||
Usage: "make",
|
||||
Brief: "创建模块文件",
|
||||
Arguments: []gcmd.Argument{
|
||||
{Name: "model", Short: "m", Brief: "模块名"},
|
||||
{Name: "id", Short: "i", Brief: "活动id"},
|
||||
{Name: "name", Short: "n", Brief: "服务文件名"},
|
||||
},
|
||||
Examples: "make -m act -i 1: 创建活动1的接口与服务文件 \n" +
|
||||
"make -m logic -n test: 创建test的服务文件 \n" +
|
||||
"make -m config -n test: 创建配置文件 \n" +
|
||||
"make -m socket -n test: 创建socket文件 \n",
|
||||
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
||||
|
||||
//g.Dump(parser.GetOptAll(), parser.GetArgAll())
|
||||
//return
|
||||
var model = parser.GetOpt("model").String()
|
||||
//var name = parser.GetOpt("n").String()
|
||||
this := cMake{}
|
||||
switch model {
|
||||
case "act":
|
||||
var id = parser.GetOpt("id").Int()
|
||||
if id == 0 {
|
||||
return
|
||||
}
|
||||
err = this.Act(id)
|
||||
case "logic":
|
||||
var name = parser.GetOpt("name").String()
|
||||
if name == "" {
|
||||
return
|
||||
}
|
||||
err = this.Logic(name)
|
||||
case "config":
|
||||
var name = parser.GetOpt("name").String()
|
||||
if name == "" {
|
||||
return
|
||||
}
|
||||
err = this.Config(name)
|
||||
case "socket":
|
||||
var name = parser.GetOpt("name").String()
|
||||
if name == "" {
|
||||
return
|
||||
}
|
||||
err = this.Socket(name)
|
||||
}
|
||||
|
||||
return
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
type cMake struct{}
|
||||
|
||||
func (c *cMake) Api() {
|
||||
|
||||
}
|
||||
|
||||
func (c *cMake) Act(id int) (err error) {
|
||||
filePath := fmt.Sprintf("api/act/v1/act%v.go", id)
|
||||
//生成文件不覆盖
|
||||
if !gfile.Exists(filePath) {
|
||||
err = gfile.PutContents(filePath, "package v1\n")
|
||||
}
|
||||
|
||||
filePath = fmt.Sprintf("internal/game/act/act%d/act%d.go", id, id)
|
||||
//生成文件不覆盖
|
||||
if !gfile.Exists(filePath) {
|
||||
//fileStr := gfile.GetContents(getFilePath)
|
||||
get, _ := fs.ReadFile(ConfigFiles, "make/act")
|
||||
fileStr := string(get)
|
||||
fileStr = gstr.Replace(fileStr, "{id}", gconv.String(id))
|
||||
err = gfile.PutContents(filePath, fileStr)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *cMake) Logic(name string) (err error) {
|
||||
var filePath = fmt.Sprintf("internal/logic/%s/%s.go", name, name)
|
||||
//生成文件不覆盖
|
||||
if !gfile.Exists(filePath) {
|
||||
//fileStr := gfile.GetContents("./make/logic")
|
||||
get, _ := fs.ReadFile(ConfigFiles, "make/logic")
|
||||
fileStr := string(get)
|
||||
fileStr = gstr.Replace(fileStr, "{package}", name)
|
||||
fileStr = gstr.Replace(fileStr, "{name}", gstr.CaseCamel(name))
|
||||
err = gfile.PutContents(filePath, fileStr)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *cMake) Config(name string) (err error) {
|
||||
var filePath = fmt.Sprintf("utility/config/%s.go", name)
|
||||
//生成文件不覆盖
|
||||
if !gfile.Exists(filePath) {
|
||||
get, _ := fs.ReadFile(ConfigFiles, "make/config")
|
||||
fileStr := string(get)
|
||||
fileStr = gstr.Replace(fileStr, "{name}", gstr.CaseCamel(name))
|
||||
fileStr = gstr.Replace(fileStr, "{cfg}", gstr.CaseCamel(name))
|
||||
fileStr = gstr.Replace(fileStr, "{mod}", gstr.CaseCamelLower(name))
|
||||
fileStr = gstr.Replace(fileStr, "{file}", name)
|
||||
err = gfile.PutContents(filePath, fileStr)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *cMake) Socket(name string) (err error) {
|
||||
var filePath = fmt.Sprintf("internal/socket/%s/%s_new.go", name, gstr.CaseSnake(name))
|
||||
//生成文件不覆盖
|
||||
if !gfile.Exists(filePath) {
|
||||
// 生成目录文件
|
||||
get, _ := fs.ReadFile(ConfigFiles, "make/socket")
|
||||
fileStr := string(get)
|
||||
fileStr = gstr.Replace(fileStr, "{name}", name)
|
||||
err = gfile.PutContents(filePath, fileStr)
|
||||
|
||||
//生成方法文件
|
||||
var filePath2 = fmt.Sprintf("internal/socket/%s/%s.go", name, gstr.CaseSnake(name))
|
||||
get, _ = fs.ReadFile(ConfigFiles, "make/socket2")
|
||||
fileStr = string(get)
|
||||
fileStr = gstr.Replace(fileStr, "{name}", name)
|
||||
fileStr = gstr.Replace(fileStr, "{func}", gstr.CaseCamel(name))
|
||||
err = gfile.PutContents(filePath2, fileStr)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
38
cmd/make/act
Normal file
38
cmd/make/act
Normal file
@@ -0,0 +1,38 @@
|
||||
package act{id}
|
||||
|
||||
import (
|
||||
service2 "github.com/ayflying/utility_go/service"
|
||||
)
|
||||
|
||||
type sAct{id} struct {
|
||||
}
|
||||
|
||||
func New() *sAct{id} {
|
||||
return &sAct{id}{}
|
||||
}
|
||||
|
||||
var (
|
||||
ActId = {id}
|
||||
Name = ""
|
||||
)
|
||||
|
||||
type Data struct {
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
}
|
||||
|
||||
func (s *sAct{id}) GetData(uid int64) (data *Data) {
|
||||
get, _ := service2.GameAct().Info(uid, ActId)
|
||||
get.Scan(&data)
|
||||
if get.IsEmpty() || get.IsNil() || data == nil {
|
||||
data = &Data{
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sAct{id}) SetData(uid int64, data interface{}) {
|
||||
service2.GameAct().Set(uid, ActId, data)
|
||||
}
|
||||
51
cmd/make/config
Normal file
51
cmd/make/config
Normal file
@@ -0,0 +1,51 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/ayflying/utility_go/pkg"
|
||||
"github.com/gogf/gf/v2/util/gutil"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type {cfg}Cfg struct {
|
||||
Id int32 `json:"id" dc:"编号"`
|
||||
}
|
||||
|
||||
type {mod}Mod struct {
|
||||
once sync.Once
|
||||
lock sync.Mutex
|
||||
cfgArr []*{cfg}Cfg
|
||||
cfgMap map[int32]*{cfg}Cfg
|
||||
}
|
||||
|
||||
var {name} = &{mod}Mod{}
|
||||
|
||||
func (c *{mod}Mod) Load(_cfg ...string) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
c.cfgArr = make([]*{cfg}Cfg, 0)
|
||||
data, err := pkg.Config().GetFile("{file}")
|
||||
err = data.Scan(&c.cfgArr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c.cfgMap = make(map[int32]*{cfg}Cfg)
|
||||
for _, v := range c.cfgArr {
|
||||
c.cfgMap[v.Id] = v
|
||||
}
|
||||
}
|
||||
|
||||
func (c *{mod}Mod) List() []*{cfg}Cfg {
|
||||
var list = make([]*{cfg}Cfg, len(c.cfgArr))
|
||||
for k, v := range c.cfgArr {
|
||||
list[k] = c.Get(v.Id)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func (c *{mod}Mod) Get(id int32) *{cfg}Cfg {
|
||||
if data, ok := c.cfgMap[id]; ok {
|
||||
return gutil.Copy(data).(*{cfg}Cfg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
25
cmd/make/logic
Normal file
25
cmd/make/logic
Normal file
@@ -0,0 +1,25 @@
|
||||
package {package}
|
||||
|
||||
import (
|
||||
"game_server/internal/service"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
)
|
||||
|
||||
type s{name} struct {
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
)
|
||||
|
||||
func New() *s{name} {
|
||||
return &s{name}{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
service.Register{name}(New())
|
||||
}
|
||||
|
||||
func (s *s{name}) Info() {
|
||||
|
||||
}
|
||||
10
cmd/make/socket
Normal file
10
cmd/make/socket
Normal file
@@ -0,0 +1,10 @@
|
||||
package {name}
|
||||
|
||||
type {name} struct {
|
||||
}
|
||||
|
||||
func New() *{name} {
|
||||
return &{name}{}
|
||||
}
|
||||
|
||||
func init() {}
|
||||
19
cmd/make/socket2
Normal file
19
cmd/make/socket2
Normal file
@@ -0,0 +1,19 @@
|
||||
package {name}
|
||||
|
||||
import (
|
||||
"github.com/ayflying/utility_go/pkg"
|
||||
"github.com/ayflying/utility_go/pkg/websocket"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func (s *{name}) {func}Handler(conn *websocket.WebsocketData, req any) (err error) {
|
||||
var data = &v1.{func}2S{}
|
||||
err = proto.Unmarshal(req.([]byte), data)
|
||||
|
||||
var res = &v1.{func}2C{}
|
||||
|
||||
resp, err := proto.Marshal(res)
|
||||
pkg.Websocket().Send(000000, conn.Uid, resp)
|
||||
|
||||
return
|
||||
}
|
||||
267
cmd/middleware.go
Normal file
267
cmd/middleware.go
Normal file
@@ -0,0 +1,267 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/ayflying/utility_go/service"
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
)
|
||||
|
||||
//func MiddlewareAnonymous(r *ghttp.Request) {
|
||||
// // 中间件处理逻辑
|
||||
// r.Response.CORSDefault()
|
||||
//
|
||||
// ip := r.GetClientIp()
|
||||
// r.SetCtxVar("ip", ip)
|
||||
//
|
||||
// //各种回调的日志返回
|
||||
// //get, _ := r.GetJson()
|
||||
// get := r.GetRequestMapStrStr()
|
||||
// delete(get, "r")
|
||||
// delete(get, "s")
|
||||
// delete(get, "t")
|
||||
// delete(get, "data")
|
||||
// getJson, _ := gjson.EncodeString(get)
|
||||
// g.Log("cmd").Debugf(r.GetCtx(), "from|%v|%v|%v", 0, r.RequestURI, getJson)
|
||||
//
|
||||
// r.Middleware.Next()
|
||||
//
|
||||
// //中间件后置
|
||||
// err := r.GetError()
|
||||
// if err != nil {
|
||||
// code, err2 := strconv.Atoi(err.Error())
|
||||
// if err2 != nil {
|
||||
// return
|
||||
// }
|
||||
// if _, ok := consts.ErrCodeList[code]; ok {
|
||||
// //g.Dump("===error:", gerror.Code(r.GetError()).Code())
|
||||
// msg := g.Map{
|
||||
// "code": code,
|
||||
// "message": consts.ErrCodeList[code],
|
||||
// //"data": r.GetHandlerResponse(),
|
||||
// }
|
||||
// r.Response.WriteJson(msg)
|
||||
// //错误码置空
|
||||
// r.SetError(nil)
|
||||
// //g.Log("cmd").Debugf(r.GetCtx(), "to|%v|%v|%v", uid, r.RequestURI, msg)
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// //回复
|
||||
// res, _ := gjson.EncodeString(r.GetHandlerResponse())
|
||||
// g.Log("cmd").Debugf(r.GetCtx(), "to|%v|%v|%v", 0, r.RequestURI, res)
|
||||
//}
|
||||
|
||||
func MiddlewareAdmin(r *ghttp.Request) {
|
||||
// 中间件处理逻辑
|
||||
r.Response.CORSDefault()
|
||||
|
||||
ip := r.GetClientIp()
|
||||
r.SetCtxVar("ip", ip)
|
||||
|
||||
getUid := r.Cookie.Get("uid")
|
||||
|
||||
if getUid == nil {
|
||||
//调试模式允许不验证用户名
|
||||
debug, _ := g.Cfg().GetWithEnv(nil, "debug")
|
||||
if !debug.Bool() {
|
||||
|
||||
msg := g.Map{
|
||||
"code": 403,
|
||||
"message": "登录失败",
|
||||
//"data": r.GetHandlerResponse(),
|
||||
}
|
||||
//r.SetError(http.Error(r,"403",http.StatusForbidden))
|
||||
r.Response.WriteJson(msg)
|
||||
gerror.NewCode(gcode.CodeNil, "登录失败")
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uid := getUid.Int()
|
||||
|
||||
//获取所有请求的信息
|
||||
get := r.GetRequestMapStrStr()
|
||||
if _, ok := get["uid"]; ok {
|
||||
r.SetCtxVar("uid", get["uid"])
|
||||
}
|
||||
|
||||
r.Middleware.Next()
|
||||
|
||||
//后置,所有post都写入日志
|
||||
if r.Method == "POST" {
|
||||
//黑名单列表
|
||||
LogUrl := []string{
|
||||
"/system/chatgpt",
|
||||
}
|
||||
if !gstr.InArray(LogUrl, r.RequestURI) {
|
||||
//写入日志
|
||||
service.SystemLog().AddLog(uid, r.RequestURI, ip, r.GetFormMap())
|
||||
}
|
||||
} else {
|
||||
//需要写入的get
|
||||
LogUrl := []string{
|
||||
"/admin/config/mall/del",
|
||||
"/admin/config/shop/del",
|
||||
"/admin/group/del",
|
||||
"/admin/user/del",
|
||||
"/admin/community/posts/del",
|
||||
"/admin/community/posts/limit",
|
||||
"/admin/community/posts/limit/del",
|
||||
"/admin/community/reply/del",
|
||||
"/admin/community/recommend",
|
||||
}
|
||||
for _, item := range LogUrl {
|
||||
if item == r.RequestURI {
|
||||
service.SystemLog().AddLog(uid, r.RequestURI, ip, r.GetFormMap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//// 中间件
|
||||
//func Middleware(r *ghttp.Request) {
|
||||
// // 中间件处理逻辑
|
||||
// r.Response.CORSDefault()
|
||||
//
|
||||
// //获取玩家的guid
|
||||
// guid := r.Header.Get("guid")
|
||||
//
|
||||
// //获取所有请求的信息
|
||||
// get := r.GetRequestMapStrStr()
|
||||
//
|
||||
// //cacheKey := fmt.Sprintf("sign:%s", guid)
|
||||
//
|
||||
// ////进入debug模式
|
||||
// //debugBool := g.Cfg().MustGetWithCmd(nil, "debug")
|
||||
// ////如果收到签名,开始验证签名
|
||||
// //if sign, _ := get["s"]; !debugBool.Bool() && sign != "" {
|
||||
// //
|
||||
// // //如果连续两次使用相同sign,直接抛出
|
||||
// // getSign, _ := aycache.New().Get(nil, cacheKey)
|
||||
// // if getSign.String() == sign {
|
||||
// // //中间件授权错误
|
||||
// // msg := g.Map{
|
||||
// // "code": 11000,
|
||||
// // "message": consts.ErrCodeList[11000],
|
||||
// // }
|
||||
// // r.Response.WriteJson(msg)
|
||||
// // return
|
||||
// // }
|
||||
// // aycache.New().Set(nil, cacheKey, sign, time.Minute*10)
|
||||
// //
|
||||
// // secretKey := "asdkjqwhiasdoplmwofjk/aws"
|
||||
// // nonce := get["r"]
|
||||
// // timestamp := get["t"]
|
||||
// //
|
||||
// // message := timestamp + nonce
|
||||
// //
|
||||
// // timeUnix := time.Now().Unix() - gconv.Int64(timestamp)
|
||||
// // if timeUnix > 600 || timeUnix < -600 {
|
||||
// // //中间件授权错误
|
||||
// // msg := g.Map{
|
||||
// // "code": 11000,
|
||||
// // "message": consts.ErrCodeList[11000],
|
||||
// // }
|
||||
// // r.Response.WriteJson(msg)
|
||||
// // return
|
||||
// // }
|
||||
// //
|
||||
// // // 创建 HMAC 对象
|
||||
// // h := hmac.New(sha256.New, []byte(secretKey))
|
||||
// //
|
||||
// // // 更新 HMAC 对象的数据
|
||||
// // h.Write([]byte(message))
|
||||
// //
|
||||
// // // 获取 HMAC 的十六进制表示
|
||||
// // signature := hex.EncodeToString(h.Sum(nil))
|
||||
// //
|
||||
// // //如果加密算法不一致
|
||||
// // if signature != sign {
|
||||
// // //中间件授权错误
|
||||
// // msg := g.Map{
|
||||
// // "code": 11000,
|
||||
// // "message": consts.ErrCodeList[11000],
|
||||
// // }
|
||||
// // r.Response.WriteJson(msg)
|
||||
// // return
|
||||
// // }
|
||||
// //}
|
||||
//
|
||||
// uid, _ := service.MemberUser().Guid2uid(guid)
|
||||
// if uid == 0 {
|
||||
// //中间件授权错误
|
||||
// msg := g.Map{
|
||||
// "code": 11000,
|
||||
// "message": consts.ErrCodeList[11000],
|
||||
// //"data": r.GetHandlerResponse(),
|
||||
// }
|
||||
// r.Response.WriteJson(msg)
|
||||
//
|
||||
// return
|
||||
// }
|
||||
// r.SetCtxVar("guid", guid)
|
||||
// r.SetCtxVar("uid", uid)
|
||||
//
|
||||
// ip := r.GetClientIp()
|
||||
// r.SetCtxVar("ip", ip)
|
||||
//
|
||||
// delete(get, "r")
|
||||
// delete(get, "s")
|
||||
// delete(get, "t")
|
||||
// delete(get, "data")
|
||||
// //前置输出服务器收到信息
|
||||
// getJson, _ := gjson.EncodeString(get)
|
||||
// //后置输出服务器返回信息
|
||||
// if r.GetCtxVar("not_log").IsEmpty() {
|
||||
// g.Log("cmd").Debugf(r.GetCtx(), "from|%v|%v|%v", uid, r.RequestURI, getJson)
|
||||
// }
|
||||
//
|
||||
// //运行开始时间
|
||||
// RunStartTime := gtime.Now()
|
||||
//
|
||||
// //proto.Marshal()
|
||||
//
|
||||
// //中间件核心
|
||||
// r.Middleware.Next()
|
||||
//
|
||||
// //返回运行时
|
||||
// if getTime := gtime.Now().Sub(RunStartTime); getTime > time.Millisecond*1000 {
|
||||
// g.Log().Debugf(nil, "当前运行时间:%v,uid=%d,url=%s", getTime, uid, r.RequestURI)
|
||||
// }
|
||||
//
|
||||
// //中间件后置
|
||||
// err := r.GetError()
|
||||
// if err != nil {
|
||||
// code, err2 := strconv.Atoi(err.Error())
|
||||
// if err2 != nil {
|
||||
// return
|
||||
// }
|
||||
// if _, ok := consts.ErrCodeList[code]; ok {
|
||||
// //g.Dump("===error:", gerror.Code(r.GetError()).Code())
|
||||
// msg := g.Map{
|
||||
// "code": code,
|
||||
// "message": consts.ErrCodeList[code],
|
||||
// //"data": r.GetHandlerResponse(),
|
||||
// }
|
||||
// msgJson, _ := gjson.EncodeString(msg)
|
||||
// r.Response.WriteJson(msgJson)
|
||||
// //错误码置空
|
||||
// r.SetError(nil)
|
||||
// g.Log("cmd").Debugf(r.GetCtx(), "to|%v|%v|%v", uid, r.RequestURI, msg)
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// //后置输出服务器返回信息
|
||||
// if r.GetCtxVar("not_log").IsEmpty() {
|
||||
// res, _ := gjson.EncodeString(r.GetHandlerResponse())
|
||||
// g.Log("cmd").Debugf(r.GetCtx(), "to|%v|%v|%v", uid, r.RequestURI, res)
|
||||
// }
|
||||
//
|
||||
//}
|
||||
167
cmd/update.go
Normal file
167
cmd/update.go
Normal file
@@ -0,0 +1,167 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/ayflying/utility_go/pkg"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gcfg"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
)
|
||||
|
||||
type serverCfg struct {
|
||||
Name string `json:"name" dc:"服务名"`
|
||||
Address string `json:"address" dc:"服务地址"`
|
||||
Prod bool `json:"prod" dc:"是否生产环境"`
|
||||
S3 string `json:"s3" dc:"使用哪个对象储存中转"`
|
||||
Arch string `json:"arch" dc:"架构"`
|
||||
System string `json:"system" dc:"系统"`
|
||||
}
|
||||
|
||||
type UpdateReq struct {
|
||||
File *ghttp.UploadFile `json:"file" binding:"required" dc:"文件"`
|
||||
FileUrl string `json:"file_url" dc:"文件地址"`
|
||||
}
|
||||
|
||||
var (
|
||||
Update = gcmd.Command{
|
||||
Name: "update",
|
||||
Usage: "update",
|
||||
Brief: "更新系统",
|
||||
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
||||
|
||||
g.Log().Info(ctx, "准备上传更新文件")
|
||||
//加载编辑配置文件
|
||||
g.Cfg("hack").GetAdapter().(*gcfg.AdapterFile).SetFileName("hack/config.yaml")
|
||||
//获取文件名
|
||||
getFileName, err := g.Cfg("hack").Get(ctx, "gfcli.build.name")
|
||||
Filename := getFileName.String()
|
||||
|
||||
getPath, err := g.Cfg("hack").Get(ctx, "gfcli.build.path")
|
||||
Path := getPath.String()
|
||||
|
||||
//获取版本号
|
||||
getVersion, err := g.Cfg("hack").Get(ctx, "gfcli.build.version")
|
||||
Version := getVersion.String()
|
||||
|
||||
var list []*serverCfg
|
||||
serverList := g.Cfg().MustGet(ctx, "server_list")
|
||||
serverList.Scan(&list)
|
||||
|
||||
//如果有p或者prod参数,则删除prod字段为true的服务
|
||||
if parser.GetOpt("a").IsNil() {
|
||||
var temp []*serverCfg
|
||||
for _, v := range list {
|
||||
if v.Prod == false {
|
||||
temp = append(temp, v)
|
||||
}
|
||||
}
|
||||
list = temp
|
||||
} else {
|
||||
g.Dump("升级", parser.GetOpt("a"))
|
||||
}
|
||||
|
||||
g.Dump("需要更新的服务器", list)
|
||||
//获取上传链接
|
||||
var url = make(map[string]string)
|
||||
var system = make(map[string]string)
|
||||
//filename := "linux_amd64/" + Filename
|
||||
//filename := path.Join(Version, "linux_amd64", Filename)
|
||||
|
||||
client := g.Client().SetTimeout(time.Minute)
|
||||
|
||||
//循环服务器,推送更新
|
||||
for _, v := range list {
|
||||
address := v.Address
|
||||
if v.S3 == "" {
|
||||
v.S3 = "default"
|
||||
}
|
||||
|
||||
//查询当前上传地址是否存在
|
||||
_, ok2 := system[v.System+v.Arch]
|
||||
if _, ok := url[v.S3]; !ok || !ok2 {
|
||||
|
||||
var systemName = "linux_amd64"
|
||||
if v.Arch != "" && v.System != "" {
|
||||
systemName = v.System + "_" + v.Arch
|
||||
}
|
||||
var filename = path.Join(Path, Version, systemName, Filename)
|
||||
g.Log().Debugf(ctx, "当前上传文件:"+filename)
|
||||
|
||||
url[v.S3], err = UploadS3(v.S3, filename)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
return
|
||||
}
|
||||
system[v.System+v.Arch] = filename
|
||||
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
g.Log().Debugf(ctx, "准备同步服务器:%v,url=%v", v.Name, address+"/callback/update")
|
||||
get, err := client.Post(ctx, address+"/callback/update", &UpdateReq{
|
||||
FileUrl: url[v.S3],
|
||||
})
|
||||
if err != nil {
|
||||
// 读取HTTP代理环境变量(小写/大写通常都兼容,部分系统可能用大写)
|
||||
httpProxy := os.Getenv("http_proxy")
|
||||
if httpProxy == "" {
|
||||
httpProxy = os.Getenv("HTTP_PROXY")
|
||||
}
|
||||
if httpProxy == "" {
|
||||
// 读取HTTPS代理环境变量
|
||||
httpProxy = os.Getenv("https_proxy")
|
||||
if httpProxy == "" {
|
||||
httpProxy = os.Getenv("HTTPS_PROXY")
|
||||
}
|
||||
}
|
||||
// 如果没有读取到本地的代理,使用配置上传
|
||||
if httpProxy == "" {
|
||||
httpProxy = g.Cfg().MustGet(ctx, "update_proxy", "http://192.168.50.173:10808").String()
|
||||
}
|
||||
g.Log().Debugf(ctx, "切换代理进行上传:ip=%v,err=%v", httpProxy, err)
|
||||
get, err = client.Proxy(httpProxy).Post(ctx, address+"/callback/update", &UpdateReq{
|
||||
FileUrl: url[v.S3],
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
}
|
||||
defer get.Close()
|
||||
g.Log().Debugf(ctx, "同步服务器:%v,完成=%v", v.Name, address)
|
||||
}
|
||||
|
||||
return
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func UploadS3(typ string, filename string) (res string, err error) {
|
||||
//updateServerS3Name, _ := g.Config().Get(ctx, "update_server_s3_name")
|
||||
|
||||
var s3Mod = pkg.S3(typ)
|
||||
bucketName := s3Mod.GetCfg().BucketName
|
||||
obj, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer obj.Close()
|
||||
ff, err := obj.Stat()
|
||||
_, err = s3Mod.PutObject(obj, filename, bucketName, ff.Size())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
//上传当前文件
|
||||
get, err := s3Mod.GetFileUrl(filename, bucketName)
|
||||
g.Log().Debugf(gctx.New(), "下载地址:%s", get)
|
||||
|
||||
res = get.String()
|
||||
return
|
||||
}
|
||||
70
config/config.go
Normal file
70
config/config.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/apolloconfig/agollo/v4/storage"
|
||||
"github.com/ayflying/utility_go/pkg"
|
||||
"github.com/gogf/gf/contrib/config/apollo/v2"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
//ApolloCfg *apolloConfig.AppConfig
|
||||
ApolloCfg *apollo.Config
|
||||
ApolloListener []string
|
||||
Item2Obj = map[string]Load{}
|
||||
)
|
||||
|
||||
// load接口定义了Load方法,用于加载数据
|
||||
type Load interface {
|
||||
Load(cfg ...string)
|
||||
}
|
||||
|
||||
type Cfg struct {
|
||||
Lock sync.Mutex
|
||||
}
|
||||
|
||||
// Deprecated : pkg.Config().GetDbFile(name)
|
||||
func (c *Cfg) GetDbFile(name string) (res *g.Var, err error) {
|
||||
res, err = pkg.Config().GetDbFile(name)
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated : pkg.Config().GetFile(name, obj...)
|
||||
func (c *Cfg) GetFile(filename string, obj ...Load) (jsonObj *gjson.Json, err error) {
|
||||
jsonObj, err = pkg.Config().GetFile(filename)
|
||||
return
|
||||
}
|
||||
|
||||
// getUrlFile 获取远程配置
|
||||
// Deprecated : pkg.Config().GetUrlFile(name)
|
||||
func (c *Cfg) GetUrlFile(name string) (jsonObj *gjson.Json, err error) {
|
||||
jsonObj, err = pkg.Config().GetUrlFile(name)
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated : pkg.Config().GetApollo(name, obj)
|
||||
func (c *Cfg) GetApollo(name string, obj Load) (jsonObj *gjson.Json, err error) {
|
||||
jsonObj, err = pkg.Config().GetApollo(name, obj)
|
||||
return
|
||||
}
|
||||
|
||||
// 阿波罗监听器
|
||||
type CustomChangeListener struct {
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
func (c *CustomChangeListener) OnChange(changeEvent *storage.ChangeEvent) {
|
||||
g.Log().Debugf(nil, "当前Namespace变化了:%v", changeEvent.Namespace)
|
||||
filename := changeEvent.Namespace
|
||||
if obj, ok := Item2Obj[filename]; ok {
|
||||
//重载配置文件
|
||||
obj.Load(changeEvent.Changes["content"].NewValue.(string))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CustomChangeListener) OnNewestChange(event *storage.FullChangeEvent) {
|
||||
//write your code here
|
||||
|
||||
}
|
||||
5
controller/callback/callback.go
Normal file
5
controller/callback/callback.go
Normal file
@@ -0,0 +1,5 @@
|
||||
// =================================================================================
|
||||
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
// =================================================================================
|
||||
|
||||
package callback
|
||||
15
controller/callback/callback_new.go
Normal file
15
controller/callback/callback_new.go
Normal file
@@ -0,0 +1,15 @@
|
||||
// =================================================================================
|
||||
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
// =================================================================================
|
||||
|
||||
package callback
|
||||
|
||||
import (
|
||||
"github.com/ayflying/utility_go/api/callback"
|
||||
)
|
||||
|
||||
type ControllerV1 struct{}
|
||||
|
||||
func NewV1() callback.ICallbackV1 {
|
||||
return &ControllerV1{}
|
||||
}
|
||||
14
controller/callback/callback_v1_ip.go
Normal file
14
controller/callback/callback_v1_ip.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package callback
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/ayflying/utility_go/service"
|
||||
|
||||
"github.com/ayflying/utility_go/api/callback/v1"
|
||||
)
|
||||
|
||||
func (c *ControllerV1) Ip(ctx context.Context, req *v1.IpReq) (res *v1.IpRes, err error) {
|
||||
res = &v1.IpRes{}
|
||||
res.Address = service.Ip2Region().GetIp(req.Ip)
|
||||
return
|
||||
}
|
||||
14
controller/callback/callback_v1_robots.go
Normal file
14
controller/callback/callback_v1_robots.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package callback
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ayflying/utility_go/api/callback/v1"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
func (c *ControllerV1) Robots(ctx context.Context, req *v1.RobotsReq) (res *v1.RobotsRes, err error) {
|
||||
text := "User-agent: *\nDisallow: /"
|
||||
g.RequestFromCtx(ctx).Response.Write(text)
|
||||
return
|
||||
}
|
||||
83
drivers/db/elasticsearch/elasticsearch.go
Normal file
83
drivers/db/elasticsearch/elasticsearch.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package elasticsearch
|
||||
|
||||
import (
|
||||
"github.com/elastic/go-elasticsearch/v8"
|
||||
)
|
||||
|
||||
var (
|
||||
es *elasticsearch.TypedClient
|
||||
)
|
||||
|
||||
type elastic struct {
|
||||
client *elasticsearch.TypedClient
|
||||
}
|
||||
|
||||
//func (d *Driver) Insert(ctx context.Context, table string, data interface{}, batch ...int) (res sql.Result, err error) {
|
||||
//
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//// createIndex 创建索引
|
||||
//func (d *Driver) CreateIndex(name string) {
|
||||
//
|
||||
// resp, err := d.client.Indices.
|
||||
// Create(name).
|
||||
// Do(context.Background())
|
||||
// if err != nil {
|
||||
// fmt.Printf("create index failed, err:%v\n", err)
|
||||
// return
|
||||
// }
|
||||
// fmt.Printf("index:%#v\n", resp.Index)
|
||||
//}
|
||||
//
|
||||
//// indexDocument 索引文档
|
||||
//func (d *Driver) IndexDocument(name string, key string, data interface{}) {
|
||||
//
|
||||
// // 添加文档
|
||||
// resp, err := d.client.Index(name).
|
||||
// Id(key).
|
||||
// Document(data).
|
||||
// Do(context.Background())
|
||||
// if err != nil {
|
||||
// fmt.Printf("indexing document failed, err:%v\n", err)
|
||||
// return
|
||||
// }
|
||||
// fmt.Printf("result:%#v\n", resp.Result)
|
||||
//}
|
||||
//
|
||||
//// getDocument 获取文档
|
||||
//func (d *Driver) Get(name string, id string) (res json.RawMessage) {
|
||||
// resp, err := d.client.Get(name, id).
|
||||
// Do(context.Background())
|
||||
// if err != nil {
|
||||
// fmt.Printf("get document by id failed, err:%v\n", err)
|
||||
// return
|
||||
// }
|
||||
// fmt.Printf("fileds:%d\n", resp.Source_)
|
||||
// res = resp.Source_
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//// updateDocument 更新文档
|
||||
//func (d *Driver) UpdateDocument(name string, key string, data interface{}) {
|
||||
//
|
||||
// resp, err := d.client.Update(name, key).
|
||||
// Doc(data). // 使用结构体变量更新
|
||||
// Do(context.Background())
|
||||
// if err != nil {
|
||||
// fmt.Printf("update document failed, err:%v\n", err)
|
||||
// return
|
||||
// }
|
||||
// fmt.Printf("result:%v\n", resp.Result)
|
||||
//}
|
||||
//
|
||||
//// deleteDocument 删除 document
|
||||
//func (d *Driver) DeleteDocument(name string, key string) {
|
||||
// resp, err := d.client.Delete(name, key).
|
||||
// Do(context.Background())
|
||||
// if err != nil {
|
||||
// fmt.Printf("delete document failed, err:%v\n", err)
|
||||
// return
|
||||
// }
|
||||
// fmt.Printf("result:%v\n", resp.Result)
|
||||
//}
|
||||
39
drivers/db/elasticsearch/es_open.go
Normal file
39
drivers/db/elasticsearch/es_open.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package elasticsearch
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"github.com/elastic/go-elasticsearch/v8"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
)
|
||||
|
||||
func (d *Driver) Open(config *gdb.ConfigNode) (db *sql.DB, err error) {
|
||||
var (
|
||||
source string
|
||||
underlyingDriverName = "elasticsearch"
|
||||
)
|
||||
source = config.Host
|
||||
|
||||
cfg := elasticsearch.Config{
|
||||
Addresses: []string{
|
||||
config.Host,
|
||||
},
|
||||
}
|
||||
|
||||
es, err = elasticsearch.NewTypedClient(cfg)
|
||||
//if err != nil {
|
||||
// fmt.Printf("elasticsearch.NewTypedClient failed, err:%v\n", err)
|
||||
// return
|
||||
//}
|
||||
|
||||
if db, err = sql.Open(underlyingDriverName, source); err != nil {
|
||||
err = gerror.WrapCodef(
|
||||
gcode.CodeDbOperationError, err,
|
||||
`sql.Open failed for driver "%s" by source "%s"`, underlyingDriverName, source,
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
51
drivers/db/elasticsearch/load.go
Normal file
51
drivers/db/elasticsearch/load.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package elasticsearch
|
||||
|
||||
import (
|
||||
"github.com/ayflying/utility_go/internal/boot"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// Driver is the driver for mysql database.
|
||||
type Driver struct {
|
||||
*gdb.Core
|
||||
}
|
||||
|
||||
const (
|
||||
quoteChar = "`"
|
||||
)
|
||||
|
||||
func init() {
|
||||
boot.AddFunc(func() {
|
||||
var (
|
||||
err error
|
||||
driverObj = New()
|
||||
driverNames = g.SliceStr{"es", "elasticsearch"}
|
||||
)
|
||||
for _, driverName := range driverNames {
|
||||
if err = gdb.Register(driverName, driverObj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// New create and returns a driver that implements gdb.Driver, which supports operations for MySQL.
|
||||
func New() gdb.Driver {
|
||||
return &Driver{}
|
||||
}
|
||||
|
||||
// New creates and returns a database object for mysql.
|
||||
// It implements the interface of gdb.Driver for extra database driver installation.
|
||||
func (d *Driver) New(core *gdb.Core, node *gdb.ConfigNode) (res gdb.DB, err error) {
|
||||
res = &Driver{
|
||||
Core: core,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetChars returns the security char for this type of database.
|
||||
func (d *Driver) GetChars() (charLeft string, charRight string) {
|
||||
return quoteChar, quoteChar
|
||||
}
|
||||
56
drivers/db/found/found.go
Normal file
56
drivers/db/found/found.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package found
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"github.com/ayflying/utility_go/internal/boot"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// Driver is the driver for mysql database.
|
||||
type Driver struct {
|
||||
*gdb.Core
|
||||
}
|
||||
|
||||
func (d *Driver) Open(config *gdb.ConfigNode) (*sql.DB, error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
const (
|
||||
quoteChar = "`"
|
||||
)
|
||||
|
||||
func init() {
|
||||
boot.AddFunc(func() {
|
||||
var (
|
||||
err error
|
||||
driverObj = New()
|
||||
driverNames = g.SliceStr{"es", "found"}
|
||||
)
|
||||
for _, driverName := range driverNames {
|
||||
if err = gdb.Register(driverName, driverObj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// New create and returns a driver that implements gdb.Driver, which supports operations for MySQL.
|
||||
func New() gdb.Driver {
|
||||
return &Driver{}
|
||||
}
|
||||
|
||||
// New creates and returns a database object for mysql.
|
||||
// It implements the interface of gdb.Driver for extra database driver installation.
|
||||
func (d *Driver) New(core *gdb.Core, node *gdb.ConfigNode) (res gdb.DB, err error) {
|
||||
res = &Driver{
|
||||
Core: core,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetChars returns the security char for this type of database.
|
||||
func (d *Driver) GetChars() (charLeft string, charRight string) {
|
||||
return quoteChar, quoteChar
|
||||
}
|
||||
174
excel/excel.go
174
excel/excel.go
@@ -1,174 +0,0 @@
|
||||
package excel
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/ayflying/excel2json"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type FileItem struct {
|
||||
Name string `json:"name" dc:"配置文件名"`
|
||||
Filename string `json:"filename" dc:"文件名"`
|
||||
Tabs []string `json:"tabs" dc:"页签"`
|
||||
Items []string `json:"items" dc:"道具字段"`
|
||||
ItemsMap []string `json:"items_map" dc:"道具字段map格式"`
|
||||
Slice map[string]string `json:"slice" dc:"切片"`
|
||||
}
|
||||
|
||||
type Excel struct {
|
||||
Header int //表头行数
|
||||
Key int //key列
|
||||
}
|
||||
|
||||
func New(header int, key int) *Excel {
|
||||
return &Excel{
|
||||
Header: header,
|
||||
Key: key,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Excel) ExcelLoad(ctx context.Context, fileItem *FileItem, mainPath string) (runTime time.Duration) {
|
||||
startTime := gtime.Now()
|
||||
filepath := path.Join("manifest/game", fileItem.Name)
|
||||
|
||||
//如果filepath文件不存在,跳过
|
||||
if !gfile.Exists(path.Join(mainPath, fileItem.Filename)) {
|
||||
return
|
||||
}
|
||||
|
||||
//假设我们有一个命令行工具,比如:dir(Windows环境下列出目录内容)
|
||||
var tempJson []interface{}
|
||||
for k, v2 := range fileItem.Tabs {
|
||||
sheet := v2
|
||||
if k == 0 {
|
||||
sheet = v2
|
||||
}
|
||||
|
||||
//导出json
|
||||
excel2json.Excel(path.Join(mainPath, fileItem.Filename),
|
||||
filepath, s.Header, s.Key, sheet)
|
||||
|
||||
//如果配置了道具字段,则进行转换
|
||||
//g.Log().Info(ctx, "当前任务表=%v,items=%v", v.Name, v.Items)
|
||||
fileBytes := gfile.GetBytes(filepath)
|
||||
arr, _ := gjson.DecodeToJson(fileBytes)
|
||||
list := arr.Array()
|
||||
//格式化item格式
|
||||
if len(fileItem.Items) > 0 {
|
||||
list = s.itemsFormat(list, fileItem.Items)
|
||||
}
|
||||
if len(fileItem.ItemsMap) > 0 {
|
||||
list = s.itemsMapFormat(list, gconv.Strings(fileItem.ItemsMap))
|
||||
}
|
||||
//格式化切片修改
|
||||
if len(fileItem.Slice) > 0 {
|
||||
list = s.sliceFormat(list, fileItem.Slice)
|
||||
}
|
||||
|
||||
//拼接json
|
||||
tempJson = append(tempJson, list...)
|
||||
fileBytes, _ = gjson.MarshalIndent(tempJson, "", "\t")
|
||||
err := gfile.PutBytes(filepath, fileBytes)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
}
|
||||
}
|
||||
|
||||
runTime = gtime.Now().Sub(startTime)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Excel) itemsFormat(list []interface{}, Items []string) []interface{} {
|
||||
for k2, v2 := range list {
|
||||
for k3, v3 := range v2.(g.Map) {
|
||||
if gstr.InArray(Items, k3) {
|
||||
if _, ok := v3.(string); ok {
|
||||
list[k2].(g.Map)[k3] = s.Spilt2Item(v3.(string))
|
||||
|
||||
} else {
|
||||
g.Log().Errorf(gctx.New(), "当前类型断言失败:%v,list=%v", v3, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func (s *Excel) itemsMapFormat(list []interface{}, Items []string) []interface{} {
|
||||
for k2, v2 := range list {
|
||||
for k3, v3 := range v2.(g.Map) {
|
||||
if gstr.InArray(Items, k3) {
|
||||
if _, ok := v3.(string); ok {
|
||||
get := s.Spilt2Item(v3.(string))
|
||||
list[k2].(g.Map)[k3] = s.Items2Map(get)
|
||||
} else {
|
||||
g.Log().Errorf(gctx.New(), "当前类型断言失败:%v,list=%v", v3, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func (s *Excel) sliceFormat(list []interface{}, Slice map[string]string) []interface{} {
|
||||
for s1, s2 := range Slice {
|
||||
for k2, v2 := range list {
|
||||
for k3, v3 := range v2.(g.Map) {
|
||||
//判断是否存在
|
||||
if s1 != k3 {
|
||||
continue
|
||||
}
|
||||
if gconv.String(v3) == "" {
|
||||
list[k2].(g.Map)[k3] = []string{}
|
||||
continue
|
||||
}
|
||||
|
||||
var parts []string
|
||||
//断言是否成功
|
||||
if get, ok := v3.(string); !ok {
|
||||
//g.Log().Errorf(gctx.New(), "当前类型断言失败:%v", v3)
|
||||
parts = []string{gconv.String(v3)}
|
||||
continue
|
||||
} else {
|
||||
parts = strings.Split(get, "|") // 分割字符串
|
||||
}
|
||||
|
||||
switch s2 {
|
||||
case "int":
|
||||
var temp = make([]int, len(parts))
|
||||
for k, v := range parts {
|
||||
temp[k], _ = strconv.Atoi(v)
|
||||
}
|
||||
list[k2].(g.Map)[k3] = temp
|
||||
case "int64":
|
||||
var temp = make([]int64, len(parts))
|
||||
for k, v := range parts {
|
||||
temp[k], _ = strconv.ParseInt(v, 10, 64)
|
||||
}
|
||||
case "float64":
|
||||
var temp = make([]float64, len(parts))
|
||||
for k, v := range parts {
|
||||
temp[k], _ = strconv.ParseFloat(v, 64)
|
||||
}
|
||||
list[k2].(g.Map)[k3] = temp
|
||||
default:
|
||||
list[k2].(g.Map)[k3] = parts
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
138
go.mod
138
go.mod
@@ -1,51 +1,129 @@
|
||||
module github.com/ayflying/utility_go
|
||||
|
||||
go 1.23.0
|
||||
go 1.24.0
|
||||
|
||||
require (
|
||||
github.com/ayflying/excel2json v1.1.2
|
||||
github.com/gogf/gf/v2 v2.8.3
|
||||
github.com/minio/minio-go/v7 v7.0.82
|
||||
github.com/xuri/excelize/v2 v2.9.0
|
||||
github.com/apolloconfig/agollo/v4 v4.4.0
|
||||
github.com/ayflying/excel2json v1.1.9
|
||||
github.com/casdoor/casdoor-go-sdk v1.39.0
|
||||
github.com/elastic/go-elasticsearch/v8 v8.19.0
|
||||
github.com/getlantern/systray v1.2.2
|
||||
github.com/go-pay/crypto v0.0.1
|
||||
github.com/go-pay/gopay v1.5.115
|
||||
github.com/go-pay/util v0.0.4
|
||||
github.com/goccy/go-json v0.10.5
|
||||
github.com/gogf/gf/contrib/config/apollo/v2 v2.9.6
|
||||
github.com/gogf/gf/contrib/config/consul/v2 v2.9.7
|
||||
github.com/gogf/gf/v2 v2.9.7
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/hashicorp/consul/api v1.24.0
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2
|
||||
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20251207115101-d4b8f9f841b9
|
||||
github.com/minio/minio-go/v7 v7.0.97
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
github.com/xuri/excelize/v2 v2.10.0
|
||||
golang.org/x/oauth2 v0.33.0
|
||||
google.golang.org/api v0.257.0
|
||||
google.golang.org/protobuf v1.36.10
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/360EntSecGroup-Skylar/excelize v1.4.1 // indirect
|
||||
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||
cloud.google.com/go/auth v0.17.0 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.9.0 // indirect
|
||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||
github.com/clipperhouse/displaywidth v0.6.1 // indirect
|
||||
github.com/clipperhouse/stringish v0.1.1 // indirect
|
||||
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/elastic/elastic-transport-go/v8 v8.8.0 // indirect
|
||||
github.com/emirpasic/gods/v2 v2.0.0-alpha // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/getlantern/context v0.0.0-20220418194847-3d5e7a086201 // indirect
|
||||
github.com/getlantern/errors v1.0.4 // indirect
|
||||
github.com/getlantern/golog v0.0.0-20230503153817-8e72de7e0a65 // indirect
|
||||
github.com/getlantern/hex v0.0.0-20220104173244-ad7e4b9194dc // indirect
|
||||
github.com/getlantern/hidden v0.0.0-20220104173330-f221c5a24770 // indirect
|
||||
github.com/getlantern/ops v0.0.0-20231025133620-f368ab734534 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/go-pay/errgroup v0.0.3 // indirect
|
||||
github.com/go-pay/smap v0.0.2 // indirect
|
||||
github.com/go-pay/xlog v0.0.3 // indirect
|
||||
github.com/go-pay/xtime v0.0.2 // indirect
|
||||
github.com/go-stack/stack v1.8.1 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.7 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/grokify/html-strip-tags-go v0.1.0 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||
github.com/magiconair/properties v1.8.9 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/hashicorp/go-hclog v1.5.0 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/hashicorp/serf v0.10.1 // indirect
|
||||
github.com/klauspost/compress v1.18.2 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/klauspost/crc32 v1.3.0 // indirect
|
||||
github.com/magiconair/properties v1.8.10 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.19 // indirect
|
||||
github.com/minio/crc64nvme v1.1.1 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect
|
||||
github.com/olekukonko/errors v1.1.0 // indirect
|
||||
github.com/olekukonko/ll v0.1.3 // indirect
|
||||
github.com/olekukonko/tablewriter v1.1.2 // indirect
|
||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/philhofer/fwd v1.2.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.66.1 // indirect
|
||||
github.com/prometheus/procfs v0.17.0 // indirect
|
||||
github.com/richardlehane/mscfb v1.0.4 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.4 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rs/xid v1.6.0 // indirect
|
||||
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect
|
||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
|
||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||
golang.org/x/crypto v0.30.0 // indirect
|
||||
golang.org/x/net v0.32.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.12.0 // indirect
|
||||
github.com/spf13/afero v1.15.0 // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/spf13/viper v1.21.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/tiendc/go-deepcopy v1.7.2 // indirect
|
||||
github.com/tinylib/msgp v1.6.1 // indirect
|
||||
github.com/xuri/efp v0.0.1 // indirect
|
||||
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect
|
||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.1 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.45.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/text v0.31.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251124214823-79d6a2a48846 // indirect
|
||||
google.golang.org/grpc v1.77.0 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
18
hack/config.yaml
Normal file
18
hack/config.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
# CLI tool, only in development environment.
|
||||
# https://goframe.org/pages/viewpage.action?pageId=3673173
|
||||
gfcli:
|
||||
gen:
|
||||
ctrl:
|
||||
dstFolder: "controller"
|
||||
service:
|
||||
dstFolder: "service"
|
||||
pb:
|
||||
path: "manifest/protobuf"
|
||||
api: "api"
|
||||
ctrl: "controller"
|
||||
docker:
|
||||
build: "-a amd64 -s linux -p temp -ew"
|
||||
tagPrefixes:
|
||||
- "hub.docker.com"
|
||||
# - "git.7cuu.com"
|
||||
tag: "latest"
|
||||
43
internal/boot/boot.go
Normal file
43
internal/boot/boot.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package boot
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
v1 "github.com/ayflying/utility_go/api/system/v1"
|
||||
"github.com/ayflying/utility_go/service"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = gctx.GetInitCtx()
|
||||
_func = []func(){}
|
||||
)
|
||||
|
||||
func Boot() (err error) {
|
||||
// 启动计划任务定时器,预防debug工具激活计划任务造成重复执行,此处不执行计划任务
|
||||
//err = service.SystemCron().StartCron()
|
||||
|
||||
//用户活动持久化每小时执行一次
|
||||
service.SystemCron().AddCronV2(v1.CronType_HOUR, func(context.Context) error {
|
||||
go func() {
|
||||
err = service.GameKv().SavesV1()
|
||||
err = service.GameAct().SavesV2()
|
||||
if err != nil {
|
||||
g.Log().Error(gctx.New(), err)
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}, true)
|
||||
|
||||
//初始化自启动方法
|
||||
for _, v := range _func {
|
||||
v()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddFunc 注册方法,在启动时执行
|
||||
func AddFunc(f func()) {
|
||||
_func = append(_func, f)
|
||||
}
|
||||
53
internal/game/act/act.go
Normal file
53
internal/game/act/act.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package act
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ayflying/utility_go/pgk"
|
||||
"github.com/ayflying/utility_go/service"
|
||||
"github.com/gogf/gf/v2/container/gvar"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
Cache = pgk.Cache("redis")
|
||||
ActIdListIsShow map[int]func(uid int64) bool
|
||||
RedDotList map[string]func(uid int64) int32
|
||||
)
|
||||
|
||||
func GetCacheKey(uid int64, actId int) string {
|
||||
return fmt.Sprintf("actRedDot:%s:%d:%d", gtime.Now().Format("Ymd"), actId, uid)
|
||||
}
|
||||
|
||||
// 刷新缓存
|
||||
func RefreshCache(uid int64, actId int) {
|
||||
|
||||
Cache.Remove(gctx.New(), GetCacheKey(uid, actId))
|
||||
service.GameAct().RefreshGetRedDotCache(uid)
|
||||
}
|
||||
|
||||
func GetRedDot(uid int64, actId int) *gvar.Var {
|
||||
get, _ := Cache.Get(nil, GetCacheKey(uid, actId))
|
||||
return get
|
||||
}
|
||||
|
||||
func SetRedDot(uid int64, actId int, redDot int32) {
|
||||
Cache.Set(nil, GetCacheKey(uid, actId), redDot, time.Hour)
|
||||
}
|
||||
|
||||
// 注册隐藏活动接口
|
||||
func AddIsShowRegistrar(actId int, isShow func(uid int64) bool) {
|
||||
if ActIdListIsShow == nil {
|
||||
ActIdListIsShow = make(map[int]func(uid int64) bool)
|
||||
}
|
||||
ActIdListIsShow[actId] = isShow
|
||||
}
|
||||
|
||||
// 注册红点接口
|
||||
func AddRedDotRegistrar(key string, redDot func(uid int64) int32) {
|
||||
if RedDotList == nil {
|
||||
RedDotList = make(map[string]func(uid int64) int32)
|
||||
}
|
||||
RedDotList[key] = redDot
|
||||
}
|
||||
60
internal/logic/casdoor/casdoor.go
Normal file
60
internal/logic/casdoor/casdoor.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package casdoor
|
||||
|
||||
import (
|
||||
"github.com/ayflying/utility_go/service"
|
||||
"github.com/casdoor/casdoor-go-sdk/casdoorsdk"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
)
|
||||
|
||||
type sCasdoor struct {
|
||||
client *casdoorsdk.Client
|
||||
config *casdoorsdk.AuthConfig
|
||||
}
|
||||
|
||||
func init() {
|
||||
var casdoor = &sCasdoor{}
|
||||
|
||||
service.RegisterCasdoor(New(casdoor))
|
||||
}
|
||||
|
||||
func New(s *sCasdoor) *sCasdoor {
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *sCasdoor) Load(endpoint string, clientId string, clientSecret string, certificate string, organizationName string, applicationName string) {
|
||||
s.config = &casdoorsdk.AuthConfig{
|
||||
Endpoint: endpoint,
|
||||
ClientId: clientId,
|
||||
ClientSecret: clientSecret,
|
||||
Certificate: certificate,
|
||||
OrganizationName: organizationName,
|
||||
ApplicationName: applicationName,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sCasdoor) New() *casdoorsdk.Client {
|
||||
if s.config == nil {
|
||||
g.Log().Errorf(gctx.New(), "未读取到配置,请先加载Load方法")
|
||||
return nil
|
||||
}
|
||||
s.client = casdoorsdk.NewClient(
|
||||
s.config.Endpoint,
|
||||
s.config.ClientId,
|
||||
s.config.ClientSecret,
|
||||
s.config.Certificate,
|
||||
s.config.OrganizationName,
|
||||
s.config.ApplicationName,
|
||||
)
|
||||
return s.client
|
||||
}
|
||||
|
||||
//func (s *sCasdoor) EditPassword(name, oldPassword, newPassword string) (res bool, err error) {
|
||||
// res, err = s.client.SetPassword(s.config.OrganizationName, name, oldPassword, newPassword)
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func (s *sCasdoor) Edit() {
|
||||
// s.client.GetGroups()
|
||||
//
|
||||
//}
|
||||
661
internal/logic/gameAct/gameAct.go
Normal file
661
internal/logic/gameAct/gameAct.go
Normal file
@@ -0,0 +1,661 @@
|
||||
package gameAct
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ayflying/utility_go/internal/model/do"
|
||||
"github.com/ayflying/utility_go/internal/model/entity"
|
||||
"github.com/ayflying/utility_go/pkg"
|
||||
service2 "github.com/ayflying/utility_go/service"
|
||||
"github.com/ayflying/utility_go/tools"
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
var (
|
||||
Name = "game_act"
|
||||
ActList = gset.New(true)
|
||||
RunTimeMax *gtime.Time
|
||||
TaskMax int64 = 100
|
||||
)
|
||||
|
||||
type sGameAct struct {
|
||||
}
|
||||
|
||||
func new() *sGameAct {
|
||||
return &sGameAct{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
service2.RegisterGameAct(new())
|
||||
}
|
||||
|
||||
// Info 获取活动信息
|
||||
//
|
||||
// @Description: 根据用户ID和活动ID获取活动信息
|
||||
// @receiver s *sGameAct: 代表活动操作的结构体实例
|
||||
// @param uid int64: 用户ID
|
||||
// @param actId int: 活动ID
|
||||
// @return data *v1.Act: 返回活动信息结构体指针
|
||||
// @return err error: 返回错误信息
|
||||
func (s *sGameAct) Info(uid int64, actId int) (data *g.Var, err error) {
|
||||
var ctx = gctx.New()
|
||||
if uid == 0 || actId == 0 {
|
||||
g.Log().Error(ctx, "当前参数为空")
|
||||
return
|
||||
}
|
||||
|
||||
// 构造缓存键名
|
||||
keyCache := fmt.Sprintf("act:%v:%v", actId, uid)
|
||||
// 尝试从Redis缓存中获取活动信息
|
||||
get, err := g.Redis().Get(ctx, keyCache)
|
||||
if !get.IsEmpty() {
|
||||
// 如果缓存中存在,将数据扫描到data结构体中并返回
|
||||
data = get
|
||||
return
|
||||
}
|
||||
// 从数据库中查询活动信息
|
||||
getDb, err := g.Model(Name).Where(do.GameAct{
|
||||
Uid: uid,
|
||||
ActId: actId,
|
||||
}).Fields("action").OrderDesc("updated_at").Value()
|
||||
getDb.Scan(&data)
|
||||
|
||||
if data == nil || data.IsEmpty() {
|
||||
return
|
||||
}
|
||||
// 将查询到的活动信息保存到Redis缓存中
|
||||
_, err = g.Redis().Set(ctx, keyCache, data)
|
||||
|
||||
var CacheKey = fmt.Sprintf("act:update:%d", uid)
|
||||
pkg.Cache("redis").Set(ctx, CacheKey, uid, time.Hour*24*3+time.Hour*12)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Set 将指定用户的活动信息存储到Redis缓存中。
|
||||
//
|
||||
// @Description:
|
||||
// @receiver s *sGameAct: 表示sGameAct类型的实例。
|
||||
// @param uid int64: 用户的唯一标识。
|
||||
// @param actId int: 活动的唯一标识。
|
||||
// @param data interface{}: 要存储的活动信息数据。
|
||||
// @return err error: 返回错误信息,如果操作成功,则返回nil。
|
||||
func (s *sGameAct) Set(uid int64, actId int, data interface{}) (err error) {
|
||||
var ctx = gctx.New()
|
||||
if uid == 0 || actId == 0 {
|
||||
g.Log().Error(ctx, "当前参数为空")
|
||||
return
|
||||
}
|
||||
// 构造缓存键名
|
||||
keyCache := fmt.Sprintf("act:%v:%v", actId, uid)
|
||||
if data == nil {
|
||||
_, err = g.Redis().Del(ctx, keyCache)
|
||||
return
|
||||
}
|
||||
|
||||
// 将活动信息保存到Redis缓存,并将用户ID添加到活动索引集合中
|
||||
_, err = g.Redis().Set(ctx, keyCache, data)
|
||||
|
||||
//插入集合
|
||||
ActList.Add(actId)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Saves 保存游戏活动数据
|
||||
//
|
||||
// @Description: 保存游戏活动数据
|
||||
// @receiver s *sGameAct: 游戏活动服务结构体指针
|
||||
// @return err error: 返回错误信息
|
||||
// Deprecated: 该方法已被弃用,建议使用SavesV2方法
|
||||
func (s *sGameAct) Saves() (err error) {
|
||||
var ctx = gctx.New()
|
||||
g.Log().Debug(ctx, "开始执行游戏act数据保存了")
|
||||
//如果没有执行过,设置时间戳
|
||||
// 最大允许执行时间
|
||||
RunTimeMax = gtime.Now().Add(time.Minute * 30)
|
||||
//遍历执行
|
||||
ActList.Iterator(func(i interface{}) bool {
|
||||
//在时间内允许执行
|
||||
if gtime.Now().Before(RunTimeMax) {
|
||||
g.Log().Debugf(ctx, "开始执行游戏act数据保存:act=%v", i)
|
||||
err = s.Save(ctx, i.(int))
|
||||
} else {
|
||||
g.Log().Errorf(ctx, "游戏act数据保存超时:act=%v", i)
|
||||
}
|
||||
return true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Save 保存游戏活动数据
|
||||
//
|
||||
// @Description: 保存游戏活动数据
|
||||
// @receiver s *sGameAct: 游戏活动服务结构体指针
|
||||
// @param ctx context.Context: 上下文对象
|
||||
// @param actId int: 活动ID
|
||||
// @return err error: 返回错误信息
|
||||
// deprecated: 该方法已被弃用,建议使用SaveV2方法
|
||||
func (s *sGameAct) Save(ctx context.Context, actId int) (err error) {
|
||||
|
||||
cacheKey := fmt.Sprintf("act:%v:*", actId)
|
||||
var add = make([]*entity.GameAct, 0)
|
||||
var update = make([]*entity.GameAct, 0)
|
||||
//循环获取缓存数据
|
||||
err = tools.Redis.RedisScanV2(cacheKey, func(keys []string) (err error) {
|
||||
//判断是否超时
|
||||
if gtime.Now().After(RunTimeMax) {
|
||||
g.Log().Debug(ctx, "act执行超时了,停止执行!")
|
||||
err = errors.New("act执行超时了,停止执行!")
|
||||
return
|
||||
}
|
||||
|
||||
for _, cacheKey = range keys {
|
||||
result := strings.Split(cacheKey, ":")
|
||||
actId, err = strconv.Atoi(result[1])
|
||||
var uid int64
|
||||
uid = gconv.Int64(result[2])
|
||||
//uid, err = strconv.ParseInt(result[2], 10, 64)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
continue
|
||||
}
|
||||
|
||||
cacheGet, _ := g.Redis().Get(ctx, cacheKey)
|
||||
|
||||
if uid == 0 {
|
||||
//跳过为空的用户缓存
|
||||
continue
|
||||
}
|
||||
if cacheGet.IsEmpty() {
|
||||
//空数据也不保存
|
||||
continue
|
||||
}
|
||||
|
||||
//如果有活跃,跳过持久化
|
||||
if getBool, _ := pkg.Cache("redis").
|
||||
Contains(ctx, fmt.Sprintf("act:update:%d", uid)); getBool {
|
||||
continue
|
||||
}
|
||||
|
||||
//获取数据库数据
|
||||
var data *entity.GameAct
|
||||
// 从数据库中查询活动信息
|
||||
err = g.Model(Name).Where(do.GameAct{
|
||||
Uid: uid,
|
||||
ActId: actId,
|
||||
}).Fields("uid,act_id").Scan(&data)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "当前数据错误: %v", cacheKey)
|
||||
continue
|
||||
}
|
||||
actionData := cacheGet.String()
|
||||
if data == nil {
|
||||
add = append(add, &entity.GameAct{
|
||||
ActId: actId,
|
||||
Uid: uid,
|
||||
Action: actionData,
|
||||
})
|
||||
} else {
|
||||
//覆盖数据
|
||||
data.ActId = actId
|
||||
data.Uid = uid
|
||||
data.Action = actionData
|
||||
update = append(update, data)
|
||||
}
|
||||
}
|
||||
|
||||
//批量写入数据库
|
||||
updateCount := 0
|
||||
|
||||
//g.Log().Debugf(ctx, "当前 %v 要更新的数据: %v 条", actId, len(update))
|
||||
if len(update) > 100 {
|
||||
for _, v := range update {
|
||||
v.UpdatedAt = gtime.Now()
|
||||
updateRes, err2 := g.Model(Name).Where(do.GameAct{
|
||||
Uid: v.Uid,
|
||||
ActId: v.ActId,
|
||||
}).Data(v).Update()
|
||||
if err2 != nil {
|
||||
g.Log().Error(ctx, err2)
|
||||
return
|
||||
}
|
||||
if row, _ := updateRes.RowsAffected(); row == 0 {
|
||||
g.Log().Error(ctx, "本次更新为0,更新数据失败: %v", v)
|
||||
continue
|
||||
}
|
||||
|
||||
//删除缓存
|
||||
s.DelCacheKey(ctx, v.ActId, v.Uid)
|
||||
|
||||
updateCount++
|
||||
update = make([]*entity.GameAct, 0)
|
||||
}
|
||||
g.Log().Debugf(ctx, "当前 %v 更新数据库: %v 条", actId, updateCount)
|
||||
update = make([]*entity.GameAct, 0)
|
||||
}
|
||||
|
||||
var count int64
|
||||
//g.Log().Debugf(ctx, "当前 %v 要添加的数据: %v 条", actId, len(add))
|
||||
if len(add) > 100 {
|
||||
dbRes, err2 := g.Model(Name).Data(add).Save()
|
||||
|
||||
err = err2
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err2)
|
||||
return
|
||||
}
|
||||
count, _ = dbRes.RowsAffected()
|
||||
if count == 0 {
|
||||
g.Log().Error(ctx, "当前 %v 写入数据库: %v 条", actId, count)
|
||||
for _, vTemp := range add {
|
||||
g.Log().Debugf(ctx, "当前act:%v,add写入数据: %v,内容:%v", vTemp.ActId, vTemp.Uid, vTemp.Action)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//for _, v2 := range add {
|
||||
// //删除缓存
|
||||
// s.DelCacheKey(ctx, v2.ActId, v2.Uid)
|
||||
//}
|
||||
|
||||
//g.Log().Debugf(ctx, "当前 %v 写入数据库: %v 条", actId, count)
|
||||
add = make([]*entity.GameAct, 0)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, "当前临时数据入库失败: %v", err)
|
||||
}
|
||||
|
||||
return err
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SavesV2 保存游戏活动数据
|
||||
//
|
||||
// @Description: 保存游戏活动数据
|
||||
// @receiver s *sGameAct: 游戏活动服务结构体指针
|
||||
// @return err error: 返回错误信息
|
||||
// SavesV2 保存游戏活动数据
|
||||
func (s *sGameAct) SavesV2() (err error) {
|
||||
var ctx = gctx.New()
|
||||
g.Log().Debug(ctx, "开始执行游戏act数据保存了")
|
||||
RunTimeMax = gtime.Now().Add(time.Minute * 30)
|
||||
|
||||
// 使用局部通道替代包级通道,避免并发冲突
|
||||
addChan := make(chan *entity.GameAct, 1000)
|
||||
updateChan := make(chan *entity.GameAct, 1000)
|
||||
|
||||
errChan := make(chan error, 1)
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1) // 仅需添加1次(对应Cache2SqlChan协程)
|
||||
// wg.Add(1) // 移除多余的Add调用,避免计数不平衡
|
||||
|
||||
go func() {
|
||||
defer wg.Done() // Cache2SqlChan协程完成后减1
|
||||
s.Cache2SqlChan(ctx, addChan, updateChan)
|
||||
}()
|
||||
|
||||
go func() {
|
||||
scanErr := tools.Redis.RedisScanV2("act:*", func(keys []string) error {
|
||||
if gtime.Now().After(RunTimeMax) {
|
||||
return errors.New("redis扫描超时")
|
||||
}
|
||||
for _, key := range keys {
|
||||
if keyErr := s.SaveV2(ctx, key, addChan, updateChan); keyErr != nil {
|
||||
g.Log().Errorf(ctx, "处理key %s失败: %v", key, keyErr)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
close(addChan)
|
||||
close(updateChan)
|
||||
errChan <- scanErr
|
||||
}()
|
||||
|
||||
// 等待扫描和处理完成,同时监听上下文取消
|
||||
select {
|
||||
case scanErr := <-errChan:
|
||||
wg.Wait() // 等待Cache2SqlChan处理完剩余数据
|
||||
if scanErr != nil {
|
||||
return gerror.New(fmt.Sprintf("Redis扫描失败: %v", scanErr))
|
||||
}
|
||||
case <-ctx.Done():
|
||||
wg.Wait()
|
||||
return ctx.Err() // 返回上下文取消原因
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SaveV2 保存游戏活动数据
|
||||
//
|
||||
// @Description: 保存游戏活动数据
|
||||
// @receiver s *sGameAct: 游戏活动服务结构体指针
|
||||
// @param ctx context.Context: 上下文对象
|
||||
// @param cacheKey string: 缓存键
|
||||
// @param add []*entity.GameAct: 添加数据
|
||||
// @param update []*entity.GameAct: 更新数据
|
||||
// @return err error: 返回错误信息
|
||||
func (s *sGameAct) SaveV2(ctx context.Context, cacheKey string, addChan, updateChan chan *entity.GameAct) (err error) {
|
||||
|
||||
result := strings.Split(cacheKey, ":")
|
||||
actId := gconv.Int(result[1])
|
||||
if actId == 0 {
|
||||
return
|
||||
}
|
||||
var uid int64
|
||||
uid = gconv.Int64(result[2])
|
||||
if uid == 0 {
|
||||
//跳过为空的用户缓存
|
||||
return
|
||||
}
|
||||
|
||||
//获取缓存数据
|
||||
cacheGet, _ := g.Redis().Get(ctx, cacheKey)
|
||||
|
||||
if cacheGet.IsEmpty() {
|
||||
//空数据也不保存
|
||||
return
|
||||
}
|
||||
|
||||
//如果有活跃,跳过持久化
|
||||
if getBool, _ := pkg.Cache("redis").
|
||||
Contains(ctx, fmt.Sprintf("act:update:%d", uid)); getBool {
|
||||
return
|
||||
}
|
||||
|
||||
//获取数据库数据
|
||||
var data *entity.GameAct
|
||||
// 从数据库中查询活动信息
|
||||
err = g.Model(Name).Where(do.GameAct{
|
||||
Uid: uid,
|
||||
ActId: actId,
|
||||
}).Fields("uid,act_id").Scan(&data)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "当前数据错误: %v", cacheKey)
|
||||
return
|
||||
}
|
||||
|
||||
//如果没有数据,添加
|
||||
actionData := cacheGet.String()
|
||||
if data == nil {
|
||||
//add = append(add, &entity.GameAct{
|
||||
// ActId: actId,
|
||||
// Uid: uid,
|
||||
// Action: actionData,
|
||||
//})
|
||||
addChan <- &entity.GameAct{
|
||||
ActId: actId,
|
||||
Uid: uid,
|
||||
Action: actionData,
|
||||
}
|
||||
} else {
|
||||
//覆盖数据
|
||||
data.ActId = actId
|
||||
data.Uid = uid
|
||||
data.Action = actionData
|
||||
//update = append(update, data)
|
||||
updateChan <- data
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Cache2Sql 缓存持久化到数据库
|
||||
// @Description: 缓存持久化到数据库
|
||||
// @receiver s *sGameAct: 游戏活动服务结构体指针
|
||||
// @param ctx context.Context: 上下文对象
|
||||
// @param add []*entity.GameAct: 添加数据
|
||||
// @param update []*entity.GameAct: 更新数据
|
||||
// @return err error: 返回错误信息
|
||||
func (s *sGameAct) Cache2Sql(ctx context.Context, add, update []*entity.GameAct) {
|
||||
tx, err := g.DB().Begin(ctx)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
//批量写入数据库
|
||||
var updateCount int64
|
||||
if len(update) > 0 {
|
||||
for _, v := range update {
|
||||
v.UpdatedAt = gtime.Now()
|
||||
updateRes, err2 := tx.Model(Name).Where(do.GameAct{
|
||||
Uid: v.Uid,
|
||||
ActId: v.ActId,
|
||||
}).Data(v).Update()
|
||||
if err2 != nil {
|
||||
g.Log().Error(ctx, err2)
|
||||
continue
|
||||
}
|
||||
if row, _ := updateRes.RowsAffected(); row == 0 {
|
||||
g.Log().Error(ctx, "本次更新为0,更新数据失败: %v", v)
|
||||
continue
|
||||
}
|
||||
|
||||
updateCount++
|
||||
if updateCount > TaskMax {
|
||||
g.Log().Debugf(ctx, "act当前更新数据库: %v 条", updateCount)
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
g.Log().Debugf(ctx, "act当前更新数据库失败:%v", err)
|
||||
return
|
||||
}
|
||||
updateCount = 0
|
||||
tx, err = g.DB().Begin(ctx)
|
||||
}
|
||||
//删除缓存
|
||||
s.DelCacheKey(ctx, v.ActId, v.Uid)
|
||||
}
|
||||
//循环结束了,最后写入一波
|
||||
g.Log().Debugf(ctx, "Cache2Sql运行结束,act当前更新数据库: %v 条", updateCount)
|
||||
update = (update)[:0]
|
||||
}
|
||||
|
||||
var addCount int64
|
||||
if len(add) > 0 {
|
||||
for _, v := range add {
|
||||
addRes, err2 := tx.Model(Name).Data(v).Insert()
|
||||
if err2 != nil {
|
||||
g.Log().Error(ctx, err2)
|
||||
continue
|
||||
}
|
||||
if row, _ := addRes.RowsAffected(); row == 0 {
|
||||
g.Log().Error(ctx, "本次新增为0,新增数据失败: %v", v)
|
||||
continue
|
||||
}
|
||||
addCount++
|
||||
if addCount > TaskMax {
|
||||
g.Log().Debugf(ctx, "超过%v条,act当前写入数据库: %v 条", TaskMax, addCount)
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
g.Log().Debugf(ctx, "act当前写入数据库失败:%v", err)
|
||||
return
|
||||
}
|
||||
addCount = 0
|
||||
tx, err = g.DB().Begin(ctx)
|
||||
}
|
||||
//删除缓存
|
||||
s.DelCacheKey(ctx, v.ActId, v.Uid)
|
||||
}
|
||||
|
||||
//循环结束了,最后写入一波
|
||||
g.Log().Debugf(ctx, "Cache2Sql运行结束,act当前写入数据库: %v 条", addCount)
|
||||
add = (add)[:0]
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
return
|
||||
}
|
||||
|
||||
// Cache2AddChan 批量添加数据库
|
||||
func (s *sGameAct) Cache2SqlChan(ctx context.Context, addChan, updateChan chan *entity.GameAct) {
|
||||
//批量写入数据库计数
|
||||
var addCount int64
|
||||
//批量更新数据库计数
|
||||
var updateCount int64
|
||||
//通道关闭标志
|
||||
addClosed := false
|
||||
updateClosed := false
|
||||
//写入总数
|
||||
var addAllCount, updateAllCount int64
|
||||
|
||||
tx, err := g.DB().Begin(ctx)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 使用链式安全模式
|
||||
//var db = tx.Model(Name).Safe()
|
||||
|
||||
for {
|
||||
//检查是否两个通道都已关闭且为空
|
||||
if addClosed && updateClosed {
|
||||
break
|
||||
}
|
||||
|
||||
select {
|
||||
case v, ok := <-addChan:
|
||||
if !ok {
|
||||
addClosed = true // 仅标记关闭,不立即日志
|
||||
continue
|
||||
}
|
||||
addRes, err2 := tx.Model(Name).Data(v).Insert()
|
||||
if err2 != nil {
|
||||
g.Log().Error(ctx, err2)
|
||||
continue
|
||||
}
|
||||
if row, _ := addRes.RowsAffected(); row == 0 {
|
||||
//g.Log().Error(ctx, "本次新增为0,新增数据失败: %v", v)
|
||||
continue
|
||||
}
|
||||
row, _ := addRes.RowsAffected()
|
||||
addCount += row
|
||||
|
||||
if addCount > TaskMax {
|
||||
// g.Log().Debugf(ctx, "超过%v条,act当前写入数据库: %v 条", TaskMax, addCount)
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
g.Log().Debugf(ctx, "act当前写入数据库失败:%v", err)
|
||||
return
|
||||
}
|
||||
//清空数量前累加一下
|
||||
addAllCount += addCount
|
||||
addCount = 0
|
||||
tx, err = g.DB().Begin(ctx)
|
||||
}
|
||||
|
||||
//删除缓存
|
||||
s.DelCacheKey(ctx, v.ActId, v.Uid)
|
||||
|
||||
case v, ok := <-updateChan:
|
||||
if !ok {
|
||||
updateClosed = true // 仅标记关闭,不立即日志
|
||||
continue
|
||||
}
|
||||
v.UpdatedAt = gtime.Now()
|
||||
updateRes, err2 := tx.Model(Name).Where(do.GameAct{
|
||||
Uid: v.Uid,
|
||||
ActId: v.ActId,
|
||||
}).Data(v).Update()
|
||||
if err2 != nil {
|
||||
g.Log().Error(ctx, err2)
|
||||
continue
|
||||
}
|
||||
if row, _ := updateRes.RowsAffected(); row == 0 {
|
||||
//g.Log().Error(ctx, "本次更新为0,更新数据失败: %v", v)
|
||||
continue
|
||||
}
|
||||
updateCount++
|
||||
|
||||
if updateCount > TaskMax {
|
||||
// g.Log().Debugf(ctx, "超过%v条,act当前更新数据库: %v 条", TaskMax, updateCount)
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
g.Log().Debugf(ctx, "act当前更新数据库失败:%v", err)
|
||||
return
|
||||
}
|
||||
//清空数量前累加一下
|
||||
updateAllCount += updateCount
|
||||
updateCount = 0
|
||||
tx, err = g.DB().Begin(ctx)
|
||||
}
|
||||
|
||||
//删除缓存
|
||||
s.DelCacheKey(ctx, v.ActId, v.Uid)
|
||||
|
||||
case <-ctx.Done():
|
||||
g.Log().Debug(ctx, "act协程被上下文取消")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
addAllCount += addCount
|
||||
updateAllCount += updateCount
|
||||
// 仅在所有通道处理完毕后打印最终计数(移除中间冗余日志)
|
||||
g.Log().Debugf(ctx, "运行结束act当前写入数据库: %v 条", addAllCount)
|
||||
g.Log().Debugf(ctx, "运行结束act当前更新数据库: %v 条", updateAllCount)
|
||||
return
|
||||
}
|
||||
|
||||
// 删除缓存key
|
||||
func (s *sGameAct) DelCacheKey(ctx context.Context, aid int, uid int64) {
|
||||
go func() {
|
||||
//如果有活跃,跳过删除
|
||||
if getBool, _ := pkg.Cache("redis").
|
||||
Contains(ctx, fmt.Sprintf("act:update:%d", uid)); getBool {
|
||||
return
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("act:%v:%v", aid, uid)
|
||||
_, err := g.Redis().Del(ctx, cacheKey)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// 清空GetRedDot缓存
|
||||
func (s *sGameAct) RefreshGetRedDotCache(uid int64) {
|
||||
cacheKey := fmt.Sprintf("gameAct:GetRedDot:%s:%d", gtime.Now().Format("d"), uid)
|
||||
_, err := pkg.Cache("redis").Remove(gctx.New(), cacheKey)
|
||||
if err != nil {
|
||||
g.Log().Error(gctx.New(), err)
|
||||
g.Dump(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sGameAct) Del(uid int64, actId int) {
|
||||
var ctx = gctx.New()
|
||||
if uid == 0 || actId == 0 {
|
||||
g.Log().Error(ctx, "当前参数为空")
|
||||
return
|
||||
}
|
||||
// 构造缓存键名
|
||||
keyCache := fmt.Sprintf("act:%v:%v", actId, uid)
|
||||
|
||||
//删除活动缓存
|
||||
g.Redis().Del(ctx, keyCache)
|
||||
|
||||
//删除当前活动储存
|
||||
g.Model(Name).Where(do.GameAct{
|
||||
Uid: uid,
|
||||
ActId: actId,
|
||||
}).Delete()
|
||||
|
||||
}
|
||||
137
internal/logic/gameKv/gameKv.go
Normal file
137
internal/logic/gameKv/gameKv.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package gameKv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ayflying/utility_go/pkg"
|
||||
"github.com/ayflying/utility_go/service"
|
||||
"github.com/ayflying/utility_go/tools"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
var (
|
||||
Name = "game_kv"
|
||||
RunTimeMax *gtime.Time
|
||||
)
|
||||
|
||||
type sGameKv struct {
|
||||
Lock sync.Mutex
|
||||
}
|
||||
|
||||
func New() *sGameKv {
|
||||
return &sGameKv{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
service.RegisterGameKv(New())
|
||||
}
|
||||
|
||||
// SavesV1 方法
|
||||
//
|
||||
// @Description: 保存用户KV数据列表。
|
||||
// @receiver s: sGameKv的实例。
|
||||
// @return err: 错误信息,如果操作成功,则为nil。
|
||||
func (s *sGameKv) SavesV1() (err error) {
|
||||
var ctx = gctx.New()
|
||||
// 最大允许执行时间
|
||||
RunTimeMax = gtime.Now().Add(time.Minute * 30)
|
||||
g.Log().Debug(ctx, "开始执行游戏kv数据保存")
|
||||
|
||||
// 定义用于存储用户数据的结构体
|
||||
type ListData struct {
|
||||
Uid int64 `json:"uid"`
|
||||
Kv interface{} `json:"kv"`
|
||||
}
|
||||
var list []*ListData
|
||||
// 初始化列表,长度与keys数组一致
|
||||
list = make([]*ListData, 0)
|
||||
|
||||
// 从Redis列表中获取所有用户KV索引的键
|
||||
//keys, err := utils.RedisScan("user:kv:*")
|
||||
err = tools.Redis.RedisScanV2("user:kv:*", func(keys []string) (err error) {
|
||||
//判断是否超时
|
||||
if gtime.Now().After(RunTimeMax) {
|
||||
g.Log().Error(ctx, "kv执行超时了,停止执行!")
|
||||
err = errors.New("kv执行超时了,停止执行!")
|
||||
return
|
||||
}
|
||||
|
||||
//需要删除的key
|
||||
|
||||
// 遍历keys,获取每个用户的数据并填充到list中
|
||||
for _, cacheKey := range keys {
|
||||
//g.Log().Infof(ctx, "保存用户kv数据%v", v)
|
||||
//uid := v.Int64()
|
||||
//cacheKey = "user:kv:" + strconv.FormatInt(uid, 10)
|
||||
result := strings.Split(cacheKey, ":")
|
||||
var uid = gconv.Int64(result[2])
|
||||
if uid == 0 {
|
||||
continue
|
||||
}
|
||||
//uid, err = strconv.ParseInt(result[2], 10, 64)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
g.Redis().Del(ctx, cacheKey)
|
||||
continue
|
||||
}
|
||||
|
||||
//如果有活跃,跳过持久化
|
||||
if getBool, _ := pkg.Cache("redis").
|
||||
Contains(ctx, fmt.Sprintf("act:update:%d", uid)); getBool {
|
||||
continue
|
||||
}
|
||||
|
||||
get, _ := g.Redis().Get(ctx, cacheKey)
|
||||
var data interface{}
|
||||
get.Scan(&data)
|
||||
if data == nil {
|
||||
continue
|
||||
}
|
||||
list = append(list, &ListData{
|
||||
Uid: uid,
|
||||
Kv: data,
|
||||
})
|
||||
}
|
||||
|
||||
// 将列表数据保存到数据库
|
||||
if len(list) > 100 {
|
||||
_, err2 := g.Model("game_kv").Data(list).Save()
|
||||
if err2 != nil {
|
||||
g.Log().Error(ctx, "当前kv数据入库失败: %v", err2)
|
||||
err = err2
|
||||
return
|
||||
}
|
||||
//删除当前key
|
||||
for _, v := range list {
|
||||
s.DelCacheKey(ctx, v.Uid)
|
||||
}
|
||||
list = make([]*ListData, 0)
|
||||
}
|
||||
return
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 删除缓存key
|
||||
func (s *sGameKv) DelCacheKey(ctx context.Context, uid int64) {
|
||||
//如果有活跃,跳过删除
|
||||
if getBool, _ := pkg.Cache("redis").
|
||||
Contains(ctx, fmt.Sprintf("act:update:%d", uid)); getBool {
|
||||
return
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("user:kv:%v", uid)
|
||||
_, err := g.Redis().Del(ctx, cacheKey)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
}
|
||||
}
|
||||
164
internal/logic/ip2region/ip2region.go
Normal file
164
internal/logic/ip2region/ip2region.go
Normal file
@@ -0,0 +1,164 @@
|
||||
package ip2region
|
||||
|
||||
import (
|
||||
"net"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/ayflying/utility_go/service"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/lionsoul2014/ip2region/binding/golang/xdb"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = gctx.New()
|
||||
wait = false
|
||||
)
|
||||
|
||||
const IpDbPath = "runtime/library"
|
||||
|
||||
type sIp2region struct {
|
||||
//searcher *xdb.Searcher
|
||||
searchers map[string]*xdb.Searcher
|
||||
}
|
||||
|
||||
func New() *sIp2region {
|
||||
return &sIp2region{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
service.RegisterIp2Region(New())
|
||||
|
||||
//boot.AddFunc(func() {
|
||||
// service.Ip2Region().Load()
|
||||
//})
|
||||
}
|
||||
|
||||
//func (s *sIp2region) New() *xdb.Searcher {
|
||||
//
|
||||
// return nil
|
||||
//}
|
||||
|
||||
// Load 加载到内存中
|
||||
//
|
||||
// @Description: 加载ip2region数据库到内存中。
|
||||
|
||||
// @receiver s *sIp2region: sIp2region的实例。
|
||||
func (s *sIp2region) Load(t *xdb.Version) {
|
||||
var err error
|
||||
var url string
|
||||
//var dbPath = "runtime/library/ip2region.xdb"
|
||||
switch t {
|
||||
case xdb.IPv4:
|
||||
//url = "https://github.com/ayflying/resource/raw/refs/heads/master/attachment/ip2region_v4.xdb"
|
||||
url = "https://github.com/lionsoul2014/ip2region/raw/refs/heads/master/data/ip2region_v4.xdb"
|
||||
case xdb.IPv6:
|
||||
url = "https://github.com/lionsoul2014/ip2region/raw/refs/heads/master/data/ip2region_v6.xdb"
|
||||
}
|
||||
|
||||
if wait {
|
||||
return
|
||||
}
|
||||
filename := gfile.Basename(url)
|
||||
var IpDbFile = path.Join(IpDbPath, filename)
|
||||
g.Log().Debugf(ctx, "加载ip库文件:%v", filename)
|
||||
if gfile.IsEmpty(IpDbFile) {
|
||||
wait = true
|
||||
defer func() {
|
||||
wait = false
|
||||
}()
|
||||
g.Log().Debug(ctx, "等待下载ip库文件")
|
||||
//下载文件
|
||||
putData, err2 := g.Client().Get(ctx, url)
|
||||
if err2 != nil {
|
||||
return
|
||||
}
|
||||
err = gfile.PutBytes(IpDbFile, putData.ReadAll())
|
||||
}
|
||||
|
||||
err = xdb.VerifyFromFile(IpDbFile)
|
||||
if err != nil {
|
||||
// err 包含的验证的错误
|
||||
gfile.RemoveFile(IpDbFile)
|
||||
g.Log().Errorf(ctx, "ip库xdb file verify: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 1、从 dbPath 加载 VectorIndex 缓存,把下述 vIndex 变量全局到内存里面。
|
||||
vIndex, err := xdb.LoadVectorIndexFromFile(IpDbFile)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "failed to load vector index from `%s`: %s\n", IpDbFile, err)
|
||||
return
|
||||
}
|
||||
// 2、用全局的 vIndex 创建带 VectorIndex 缓存的查询对象。
|
||||
if s.searchers == nil {
|
||||
s.searchers = make(map[string]*xdb.Searcher)
|
||||
}
|
||||
s.searchers[t.Name], err = xdb.NewWithVectorIndex(t, IpDbFile, vIndex)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "failed to create searcher with vector index: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
//cBuff := gfile.GetBytes(IpDbFile)
|
||||
//// 基于读取的内容,创建查询对象
|
||||
//s.searchers[t.Name], err = xdb.NewWithBuffer(t, cBuff)
|
||||
//if err != nil {
|
||||
// g.Log().Errorf(ctx, "无法创建内容为的搜索器: %s", err)
|
||||
// return
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
func (s *sIp2region) GetIp(ip string) (res []string) {
|
||||
//初始化加载
|
||||
//if s.searcher == nil {
|
||||
// s.Load(xdb.IPv6)
|
||||
//}
|
||||
var searchers *xdb.Searcher
|
||||
//区分ipv6与ipv4
|
||||
if s.isIPv6(ip) {
|
||||
if s.searchers[xdb.IPv6.Name] == nil {
|
||||
s.Load(xdb.IPv6)
|
||||
}
|
||||
searchers = s.searchers[xdb.IPv6.Name]
|
||||
} else {
|
||||
if s.searchers[xdb.IPv4.Name] == nil {
|
||||
s.Load(xdb.IPv4)
|
||||
}
|
||||
searchers = s.searchers[xdb.IPv4.Name]
|
||||
}
|
||||
|
||||
res = make([]string, 5)
|
||||
if searchers == nil {
|
||||
return
|
||||
}
|
||||
|
||||
region, err := searchers.SearchByStr(ip)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res = strings.Split(region, "|")
|
||||
return
|
||||
}
|
||||
|
||||
// isIPv6 判断输入字符串是否为IPv6地址
|
||||
//
|
||||
// @Description: 通过解析输入的IP字符串判断其是否为IPv6地址。
|
||||
// @receiver s *sIp2region: 代表`sIp2region`类型的实例,本函数中未使用,可忽略。
|
||||
// @param ipStr string: 待判断的IP地址字符串。
|
||||
// @return bool: 返回true表示是IPv6地址,返回false表示不是IPv6地址。
|
||||
func (s *sIp2region) isIPv6(ipStr string) bool {
|
||||
// 尝试将输入字符串解析为IP地址
|
||||
ip := net.ParseIP(ipStr)
|
||||
// 尝试将IP地址转换为IPv4格式
|
||||
ipv4 := ip.To4()
|
||||
// 如果转换为IPv4格式不为nil,则说明是IPv4地址,返回false
|
||||
if ipv4 != nil {
|
||||
return false
|
||||
}
|
||||
// 如果无法转换为IPv4格式,则说明是IPv6地址,返回true
|
||||
return true
|
||||
}
|
||||
135
internal/logic/logData/logData.go
Normal file
135
internal/logic/logData/logData.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package logData
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/ayflying/utility_go/service"
|
||||
"github.com/ayflying/utility_go/tools"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = gctx.New()
|
||||
//pathStr = "runtime/log/logData"
|
||||
//te thinkingdata.TDAnalytics
|
||||
//logChannel chan map[string]interface{}
|
||||
//wg sync.WaitGroup
|
||||
)
|
||||
|
||||
type sLogData struct {
|
||||
}
|
||||
|
||||
func New() *sLogData {
|
||||
return &sLogData{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
service.RegisterLogData(New())
|
||||
|
||||
//加载日志模块
|
||||
//service.LogData().Load()
|
||||
|
||||
}
|
||||
|
||||
func (s *sLogData) Load() {
|
||||
//数数科技初始化配置
|
||||
|
||||
//// 创建 LogConfig 配置文件
|
||||
//config := thinkingdata.TDLogConsumerConfig{
|
||||
// Directory: pathStr, // 事件采集的文件路径
|
||||
// //FileSize: 99, //单个日志文件的最大大小(MB)
|
||||
//}
|
||||
//// 初始化 logConsumer
|
||||
//consumer, _ := thinkingdata.NewLogConsumerWithConfig(config)
|
||||
//// 创建 te 对象
|
||||
//te = thinkingdata.New(consumer)
|
||||
|
||||
//日志写入通道开启
|
||||
//logAppend()
|
||||
}
|
||||
|
||||
// UserSet 方法
|
||||
//
|
||||
// @Description: 设置用户信息。
|
||||
// @receiver s: sLogData 的实例,表示日志数据的结构体。
|
||||
// @param accountId: 账户ID,用于标识账户,是字符串格式。
|
||||
// @param uid: 用户的ID,是整型的唯一标识符。
|
||||
// @param data: 要设置的用户信息,以键值对的形式提供,是map[string]interface{}类型,支持多种用户属性。
|
||||
// @return err: 执行过程中可能出现的错误,如果执行成功,则返回nil。
|
||||
func (s *sLogData) UserSet(accountId string, uid int64, data map[string]interface{}) (err error) {
|
||||
// 将用户ID转换为字符串格式的唯一标识
|
||||
//distinctId := strconv.FormatInt(uid, 10)
|
||||
// 使用accountId和distinctId以及data来设置用户信息,此处调用外部方法完成设置。
|
||||
//te.UserSet(accountId, distinctId, data)
|
||||
data["#uid"] = uid
|
||||
data["#time"] = time.Now()
|
||||
data["#type"] = "user_set"
|
||||
//data["_id"], _ = uuid.NewUUID()
|
||||
//data["#name"] = name
|
||||
g.Log("elk").Info(nil, data)
|
||||
|
||||
//todo 暂时关闭update
|
||||
//err = s.Update(uid, data)
|
||||
return
|
||||
}
|
||||
|
||||
// Track 函数记录特定事件。
|
||||
//
|
||||
// @Description: 用于跟踪和记录一个指定事件的发生,收集相关数据。
|
||||
// @receiver s: sLogData 的实例,代表日志数据的存储或处理实体。
|
||||
// @param accountId: 账户ID,用于标识事件所属的账户。
|
||||
// @param uid: 用户的ID,一个整型数值,用于区分不同的用户。
|
||||
// @param name: 事件名称,标识所记录的具体事件。
|
||||
// @param data: 事件相关的数据映射,包含事件的详细信息。
|
||||
// @return err: 错误信息,如果操作成功则为nil。
|
||||
func (s *sLogData) Track(ctx context.Context, accountId string, uid int64, name string, data map[string]interface{}) {
|
||||
// 将用户ID转换为字符串格式的唯一标识
|
||||
//distinctId := strconv.FormatInt(uid, 10)
|
||||
// 调用te.Track函数来实际记录事件,传入账户ID、用户唯一标识、事件名称及事件数据
|
||||
//te.Track(accountId, distinctId, name, data)
|
||||
if data == nil {
|
||||
return
|
||||
}
|
||||
|
||||
data["#uid"] = uid
|
||||
data["#event_name"] = name
|
||||
data["#time"] = time.Now()
|
||||
data["#type"] = "track"
|
||||
//data["_id"], _ = uuid.NewUUID()
|
||||
//道具类型特殊格式化
|
||||
if get, ok := data["items"]; ok {
|
||||
if get != nil {
|
||||
data["items"] = tools.Tools.Items2Map(get.([][]int64))
|
||||
}
|
||||
}
|
||||
|
||||
g.Log("elk").Info(nil, data)
|
||||
//err = s.Add(data)
|
||||
//由于实时写入日志太占用资源,关闭日志写入方法
|
||||
return
|
||||
}
|
||||
|
||||
//// 上报用不了,弃用
|
||||
//func (s *sLogData) Send() (err error) {
|
||||
// consumer, err := thinkingdata.NewBatchConsumer("https://yoyatime-server-release.yoyaworld.com/callback", "dev")
|
||||
// te = thinkingdata.New(consumer)
|
||||
// err = te.Flush()
|
||||
// return
|
||||
//}
|
||||
|
||||
//func (s *sLogData) Flush() (err error) {
|
||||
// //调用flush接口数据会立即写入文件,生产环境注意避免频繁调用flush引发IO或网络开销问题
|
||||
// err = te.Flush()
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func (s *sLogData) Close() {
|
||||
// // 关闭通道,表示没有更多的日志条目需要写入
|
||||
// if logChannel != nil {
|
||||
// close(logChannel)
|
||||
// wg.Wait() // 等待通道监听goroutine结束
|
||||
// }
|
||||
//
|
||||
// te.Close()
|
||||
//}
|
||||
16
internal/logic/logic.go
Normal file
16
internal/logic/logic.go
Normal file
@@ -0,0 +1,16 @@
|
||||
// ==========================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// ==========================================================================
|
||||
|
||||
package logic
|
||||
|
||||
import (
|
||||
_ "github.com/ayflying/utility_go/internal/logic/casdoor"
|
||||
_ "github.com/ayflying/utility_go/internal/logic/gameAct"
|
||||
_ "github.com/ayflying/utility_go/internal/logic/gameKv"
|
||||
_ "github.com/ayflying/utility_go/internal/logic/ip2region"
|
||||
_ "github.com/ayflying/utility_go/internal/logic/logData"
|
||||
_ "github.com/ayflying/utility_go/internal/logic/os"
|
||||
_ "github.com/ayflying/utility_go/internal/logic/systemCron"
|
||||
_ "github.com/ayflying/utility_go/internal/logic/systemLog"
|
||||
)
|
||||
7
internal/logic/os/linux.go
Normal file
7
internal/logic/os/linux.go
Normal file
@@ -0,0 +1,7 @@
|
||||
//go:build !windows
|
||||
|
||||
package os
|
||||
|
||||
func (s *sOS) start() {
|
||||
|
||||
}
|
||||
41
internal/logic/os/os.go
Normal file
41
internal/logic/os/os.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package os
|
||||
|
||||
import (
|
||||
"github.com/ayflying/utility_go/service"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
)
|
||||
|
||||
type systrayType struct {
|
||||
Icon string `json:"icon" dc:"图标"`
|
||||
Title string `json:"title" dc:"标题"`
|
||||
Tooltip string `json:"tooltip" dc:"提示"`
|
||||
}
|
||||
|
||||
type sOS struct {
|
||||
systray *systrayType
|
||||
}
|
||||
|
||||
func New() *sOS {
|
||||
return &sOS{
|
||||
systray: &systrayType{},
|
||||
}
|
||||
}
|
||||
func init() {
|
||||
service.RegisterOS(New())
|
||||
}
|
||||
|
||||
func (s *sOS) Load(title string, tooltip string, ico string) {
|
||||
if title == "" {
|
||||
title = gcmd.GetArg(0).String()
|
||||
}
|
||||
if tooltip == "" {
|
||||
tooltip = gcmd.GetArg(0).String()
|
||||
}
|
||||
|
||||
s.systray = &systrayType{
|
||||
Icon: ico,
|
||||
Title: title,
|
||||
Tooltip: tooltip,
|
||||
}
|
||||
s.start()
|
||||
}
|
||||
43
internal/logic/os/windows.go
Normal file
43
internal/logic/os/windows.go
Normal file
@@ -0,0 +1,43 @@
|
||||
//go:build windows
|
||||
|
||||
package os
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/getlantern/systray"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
)
|
||||
|
||||
func (s *sOS) start() {
|
||||
|
||||
// 系统托盘初始化(设置图标、右键菜单)
|
||||
go systray.Run(s.onSystrayReady, s.onSystrayExit)
|
||||
}
|
||||
|
||||
// 系统托盘初始化(设置图标、右键菜单)
|
||||
func (s *sOS) onSystrayReady() {
|
||||
|
||||
iconByte := gfile.GetBytes(s.systray.Icon)
|
||||
systray.SetIcon(iconByte)
|
||||
systray.SetTitle(s.systray.Title)
|
||||
systray.SetTooltip(s.systray.Tooltip)
|
||||
|
||||
mQuit := systray.AddMenuItem("退出", "退出应用")
|
||||
// Sets the icon of a menu item. Only available on Mac and Windows.
|
||||
//mQuit.SetIcon(iconByte)
|
||||
go func() {
|
||||
<-mQuit.ClickedCh
|
||||
systray.Quit()
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
func (s *sOS) onSystrayExit() {
|
||||
// clean up here
|
||||
g.Log().Debugf(gctx.New(), "系统托盘退出")
|
||||
defer os.Exit(0)
|
||||
|
||||
}
|
||||
55
internal/logic/systemCron/listener.go
Normal file
55
internal/logic/systemCron/listener.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package systemCron
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
v1 "github.com/ayflying/utility_go/api/pkg/v1"
|
||||
"github.com/ayflying/utility_go/pkg/notice"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/gclient"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
)
|
||||
|
||||
type Status struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data struct {
|
||||
Status int `json:"status"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
func (s *sSystemCron) Guardian(DingTalkWebHook string) {
|
||||
var list []struct {
|
||||
Name string
|
||||
Address string
|
||||
}
|
||||
cfg, _ := g.Cfg().Get(gctx.New(), "serverList")
|
||||
cfg.Scan(&list)
|
||||
for _, v := range list {
|
||||
get, err := g.Client().Get(gctx.New(), v.Address+"/callback/status")
|
||||
|
||||
defer get.Close()
|
||||
if err != nil {
|
||||
notice.New(v1.NoticeType_DINGTALK, DingTalkWebHook).Send(fmt.Sprintf("监控报警:服务端访问失败 (%v 服务器),err=%v", v.Name, err))
|
||||
} else if get.StatusCode != 200 {
|
||||
notice.New(v1.NoticeType_DINGTALK, DingTalkWebHook).Send(fmt.Sprintf("监控报警:服务端访问失败 (%v 服务器),code=%v,err=%v", v.Name, get.StatusCode, err))
|
||||
} else {
|
||||
var ststus Status
|
||||
err = json.Unmarshal(get.ReadAll(), &ststus)
|
||||
if ststus.Code != 0 {
|
||||
notice.New(v1.NoticeType_DINGTALK, DingTalkWebHook).Send(fmt.Sprintf("监控报警:服务端访问失败 (%v 服务器),msg=%v", v.Name, ststus.Message))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DingTalk 发送钉钉消息
|
||||
//
|
||||
// @Description: 向指定的钉钉机器人发送消息。
|
||||
// @receiver s: 系统定时任务结构体指针。
|
||||
// @param value: 要发送的消息内容。
|
||||
// Deprecated: Use message.New(message.DingTalk, DingTalkWebHook).Send(value)
|
||||
func (s *sSystemCron) DingTalk(DingTalkWebHook string, value string) (res *gclient.Response) {
|
||||
notice.New(v1.NoticeType_DINGTALK, DingTalkWebHook).Send(value)
|
||||
return
|
||||
}
|
||||
5
internal/logic/systemCron/log2mongo.go
Normal file
5
internal/logic/systemCron/log2mongo.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package systemCron
|
||||
|
||||
func (s *sSystemCron) ReadLog() {
|
||||
|
||||
}
|
||||
421
internal/logic/systemCron/systemCron.go
Normal file
421
internal/logic/systemCron/systemCron.go
Normal file
@@ -0,0 +1,421 @@
|
||||
package systemCron
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
v1 "github.com/ayflying/utility_go/api/system/v1"
|
||||
"github.com/ayflying/utility_go/service"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcron"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/os/gtimer"
|
||||
)
|
||||
|
||||
var (
|
||||
//ctx = gctx.New()
|
||||
startTime *gtime.Time
|
||||
)
|
||||
|
||||
type TaskWithParams struct {
|
||||
// TaskFunc 原有任务函数,保持签名不变
|
||||
TaskFunc func(context.Context) error
|
||||
CronType v1.CronType
|
||||
}
|
||||
|
||||
// sSystemCron 结构体定义了系统定时任务的秒计时器。
|
||||
// 它包含了不同时间周期的任务,如秒、分钟、小时、天、周、月、年以及特定的工作日任务。
|
||||
type sSystemCron struct {
|
||||
//互斥锁
|
||||
Lock sync.Mutex
|
||||
taskChan chan TaskWithParams
|
||||
TaskTimeout time.Duration
|
||||
|
||||
// 每秒执行的任务
|
||||
SecondlyTask []func(context.Context) error
|
||||
// 每分钟执行的任务
|
||||
MinutelyTask []func(context.Context) error
|
||||
// 每小时执行的任务
|
||||
HourlyTask []func(context.Context) error
|
||||
// 每天执行的任务
|
||||
DailyTask []func(context.Context) error
|
||||
// 每周执行的任务
|
||||
WeeklyTask []func(context.Context) error
|
||||
// 每月执行的任务
|
||||
MonthlyTask []func(context.Context) error
|
||||
// 每年执行的任务
|
||||
YearlyTask []func(context.Context) error
|
||||
// 每周一执行的任务
|
||||
MondayTask []func(context.Context) error
|
||||
// 每周二执行的任务
|
||||
TuesdayTask []func(context.Context) error
|
||||
// 每周三执行的任务
|
||||
WednesdayTask []func(context.Context) error
|
||||
// 每周四执行的任务
|
||||
ThursdayTask []func(context.Context) error
|
||||
// 每周五执行的任务
|
||||
FridayTask []func(context.Context) error
|
||||
// 每周六执行的任务
|
||||
SaturdayTask []func(context.Context) error
|
||||
// 每周日执行的任务
|
||||
SundayTask []func(context.Context) error
|
||||
}
|
||||
|
||||
func New() *sSystemCron {
|
||||
return &sSystemCron{
|
||||
taskChan: make(chan TaskWithParams, 2),
|
||||
TaskTimeout: time.Minute * 60,
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
service.RegisterSystemCron(New())
|
||||
}
|
||||
|
||||
// AddCron 添加一个定时任务到相应的调度列表中。
|
||||
//
|
||||
// @Description: 根据指定的类型将函数添加到不同的任务列表中,以供后续执行。
|
||||
// 确保自定义任务正确处理上下文取消信号,即可充分发挥超时打断功能。
|
||||
// @receiver s: sSystemCron的实例,代表一个调度系统。
|
||||
// @param typ: 任务的类型,决定该任务将被添加到哪个列表中。对应不同的时间间隔。
|
||||
// @param _func: 要添加的任务函数,该函数执行时应该返回一个error。
|
||||
// deprecated: 弃用,请使用 AddCronV2
|
||||
func (s *sSystemCron) AddCron(typ v1.CronType, _func func() error) {
|
||||
//转换为带上下文的,提供打断
|
||||
var _func2 = func(ctx context.Context) error {
|
||||
return _func()
|
||||
}
|
||||
// 老版本计划任务全都是主服务器唯一执行
|
||||
s.AddCronV2(typ, _func2, true)
|
||||
}
|
||||
|
||||
// AddCronV2 添加一个定时任务到相应的调度列表中。
|
||||
//
|
||||
// @Description: 根据指定的类型将函数添加到不同的任务列表中,以供后续执行。
|
||||
// @receiver s: sSystemCron的实例,代表一个调度系统。
|
||||
// @param typ: 任务的类型,决定该任务将被添加到哪个列表中。对应不同的时间间隔。
|
||||
// @param _func: 要添加的任务函数,该函数执行时应该返回一个error。
|
||||
// @param _onlyMain: 是否只在主服务器上执行一次,true 唯一执行,false 全局执行不判断唯一
|
||||
func (s *sSystemCron) AddCronV2(typ v1.CronType, _func func(context.Context) error, _onlyMain ...bool) {
|
||||
//如果传过来的任务是需要主服务器执行一次
|
||||
if len(_onlyMain) > 0 && _onlyMain[0] {
|
||||
//判断当前是否为主服务器
|
||||
if !g.Cfg().MustGet(gctx.New(), "game.cron_main").Bool() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//加锁
|
||||
s.Lock.Lock()
|
||||
defer s.Lock.Unlock()
|
||||
//
|
||||
//ctx := gctx.New()
|
||||
//newFunc := func()
|
||||
|
||||
switch typ {
|
||||
case v1.CronType_SECOND:
|
||||
s.SecondlyTask = append(s.SecondlyTask, _func) // 将函数添加到每秒执行的任务列表中
|
||||
case v1.CronType_MINUTE:
|
||||
s.MinutelyTask = append(s.MinutelyTask, _func) // 将函数添加到每分钟执行的任务列表中
|
||||
case v1.CronType_HOUR:
|
||||
s.HourlyTask = append(s.HourlyTask, _func) // 将函数添加到每小时执行的任务列表中
|
||||
case v1.CronType_DAILY:
|
||||
s.DailyTask = append(s.DailyTask, _func) // 将函数添加到每日执行的任务列表中
|
||||
case v1.CronType_WEEK:
|
||||
s.WeeklyTask = append(s.WeeklyTask, _func) // 将函数添加到每周执行的任务列表中
|
||||
case v1.CronType_MONTH:
|
||||
s.MonthlyTask = append(s.MonthlyTask, _func) // 将函数添加到每月执行的任务列表中
|
||||
case v1.CronType_YEAR:
|
||||
s.YearlyTask = append(s.YearlyTask, _func) // 将函数添加到每年执行的任务列表中
|
||||
case v1.CronType_MONDAY:
|
||||
s.MondayTask = append(s.MondayTask, _func) // 将函数添加到每周一执行的任务列表中
|
||||
case v1.CronType_TUESDAY:
|
||||
s.TuesdayTask = append(s.TuesdayTask, _func) // 将函数添加到每周二的任务列表中
|
||||
case v1.CronType_WEDNESDAY:
|
||||
s.WednesdayTask = append(s.WednesdayTask, _func) // 将函数添加到每周三执行的任务列表中
|
||||
case v1.CronType_THURSDAY:
|
||||
s.ThursdayTask = append(s.ThursdayTask, _func) // 将函数添加到每周四执行的任务列表中
|
||||
case v1.CronType_FRIDAY:
|
||||
s.FridayTask = append(s.FridayTask, _func) // 将函数添加到每周五执行的任务列表中
|
||||
case v1.CronType_SATURDAY:
|
||||
s.SaturdayTask = append(s.SaturdayTask, _func) // 将函数添加到每周六执行的任务列表中
|
||||
case v1.CronType_SUNDAY:
|
||||
s.SundayTask = append(s.SundayTask, _func) // 将函数添加到每周日的任务列表中
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// StartCron 开始计划任务执行
|
||||
//
|
||||
// @Description:
|
||||
// @receiver s
|
||||
// @return err
|
||||
func (s *sSystemCron) StartCron() (err error) {
|
||||
//如果没有数据库配置,跳过计划任务执行
|
||||
if g.Cfg().MustGet(gctx.New(), "database") == nil {
|
||||
return
|
||||
}
|
||||
//预防重复启动
|
||||
if startTime != nil {
|
||||
return
|
||||
}
|
||||
startTime = gtime.Now()
|
||||
|
||||
g.Log().Debug(gctx.New(), "启动计划任务定时器详情")
|
||||
//每秒任务
|
||||
gtimer.SetInterval(gctx.New(), time.Second, func(ctx context.Context) {
|
||||
//g.Log().Debug(ctx, "每秒定时器")
|
||||
s.secondlyTask()
|
||||
})
|
||||
|
||||
//每分钟任务
|
||||
_, err = gcron.AddSingleton(gctx.New(), "0 * * * * *", func(ctx context.Context) {
|
||||
//g.Log().Debug(ctx, "每分钟定时器")
|
||||
s.minutelyTask()
|
||||
})
|
||||
|
||||
//每小时任务
|
||||
_, err = gcron.AddSingleton(gctx.New(), "0 0 * * * *", func(ctx context.Context) {
|
||||
g.Log().Debug(ctx, "每小时定时器")
|
||||
s.hourlyTask()
|
||||
})
|
||||
|
||||
//每天任务
|
||||
_, err = gcron.AddSingleton(gctx.New(), "0 0 0 * * *", func(ctx context.Context) {
|
||||
g.Log().Debug(ctx, "每日定时器")
|
||||
s.dailyTask()
|
||||
})
|
||||
|
||||
//每周任务
|
||||
_, err = gcron.AddSingleton(gctx.New(), "0 0 0 * * 1", func(ctx context.Context) {
|
||||
g.Log().Debug(ctx, "每周一定时器")
|
||||
s.weeklyTask(1)
|
||||
})
|
||||
//每周二的任务
|
||||
_, err = gcron.AddSingleton(gctx.New(), "0 0 0 * * 2", func(ctx context.Context) {
|
||||
g.Log().Debug(ctx, "每周二定时器")
|
||||
s.weeklyTask(2)
|
||||
})
|
||||
//周三任务
|
||||
_, err = gcron.AddSingleton(gctx.New(), "0 0 0 * * 3", func(ctx context.Context) {
|
||||
g.Log().Debug(ctx, "周三定时器")
|
||||
s.weeklyTask(3)
|
||||
})
|
||||
//周四任务
|
||||
_, err = gcron.AddSingleton(gctx.New(), "0 0 0 * * 4", func(ctx context.Context) {
|
||||
g.Log().Debug(ctx, "周四定时器")
|
||||
s.weeklyTask(4)
|
||||
})
|
||||
//周五任务
|
||||
_, err = gcron.AddSingleton(gctx.New(), "0 0 0 * * 5", func(ctx context.Context) {
|
||||
g.Log().Debug(ctx, "周五定时器")
|
||||
s.weeklyTask(5)
|
||||
})
|
||||
//周六任务
|
||||
_, err = gcron.AddSingleton(gctx.New(), "0 0 0 * * 6", func(ctx context.Context) {
|
||||
g.Log().Debug(ctx, "周六定时器")
|
||||
s.weeklyTask(6)
|
||||
})
|
||||
//周日任务
|
||||
_, err = gcron.AddSingleton(gctx.New(), "0 0 0 * * 0", func(ctx context.Context) {
|
||||
g.Log().Debug(ctx, "周日定时器")
|
||||
s.weeklyTask(7)
|
||||
})
|
||||
|
||||
//每月任务
|
||||
_, err = gcron.AddSingleton(gctx.New(), "0 0 0 1 * *", func(ctx context.Context) {
|
||||
g.Log().Debug(ctx, "每月定时器")
|
||||
s.monthlyTask()
|
||||
})
|
||||
|
||||
//每年任务
|
||||
_, err = gcron.AddSingleton(gctx.New(), "0 0 0 1 1 *", func(ctx context.Context) {
|
||||
g.Log().Debug(ctx, "每年定时器")
|
||||
s.yearlyTask()
|
||||
})
|
||||
|
||||
//统一执行方法
|
||||
s.RunFuncChan()
|
||||
return
|
||||
}
|
||||
|
||||
// 每妙任务
|
||||
func (s *sSystemCron) secondlyTask() {
|
||||
if len(s.SecondlyTask) == 0 {
|
||||
return
|
||||
}
|
||||
s.AddFuncChan(s.SecondlyTask, v1.CronType_SECOND)
|
||||
return
|
||||
}
|
||||
|
||||
// 每分钟任务
|
||||
func (s *sSystemCron) minutelyTask() {
|
||||
if len(s.MinutelyTask) == 0 {
|
||||
return
|
||||
}
|
||||
s.AddFuncChan(s.MinutelyTask, v1.CronType_MINUTE)
|
||||
return
|
||||
}
|
||||
|
||||
// 每小时任务
|
||||
func (s *sSystemCron) hourlyTask() {
|
||||
if len(s.HourlyTask) == 0 {
|
||||
return
|
||||
}
|
||||
s.AddFuncChan(s.HourlyTask, v1.CronType_HOUR)
|
||||
return
|
||||
}
|
||||
|
||||
// 每天任务
|
||||
func (s *sSystemCron) dailyTask() {
|
||||
if len(s.DailyTask) == 0 {
|
||||
return
|
||||
}
|
||||
s.AddFuncChan(s.DailyTask, v1.CronType_DAILY)
|
||||
return
|
||||
}
|
||||
|
||||
// 每周任务
|
||||
func (s *sSystemCron) weeklyTask(day int) {
|
||||
var arr []func(context.Context) error
|
||||
var cronType v1.CronType
|
||||
switch day {
|
||||
case 1:
|
||||
arr = s.MondayTask
|
||||
cronType = v1.CronType_MONDAY
|
||||
case 2:
|
||||
arr = s.TuesdayTask
|
||||
cronType = v1.CronType_TUESDAY
|
||||
case 3:
|
||||
arr = s.WednesdayTask
|
||||
cronType = v1.CronType_WEDNESDAY
|
||||
case 4:
|
||||
arr = s.ThursdayTask
|
||||
cronType = v1.CronType_THURSDAY
|
||||
case 5:
|
||||
arr = s.FridayTask
|
||||
cronType = v1.CronType_FRIDAY
|
||||
case 6:
|
||||
arr = s.SaturdayTask
|
||||
cronType = v1.CronType_SATURDAY
|
||||
case 7:
|
||||
arr = s.SundayTask
|
||||
cronType = v1.CronType_SUNDAY
|
||||
default:
|
||||
arr = s.WeeklyTask
|
||||
cronType = v1.CronType_WEEK
|
||||
return
|
||||
}
|
||||
|
||||
if len(arr) == 0 {
|
||||
return
|
||||
}
|
||||
s.AddFuncChan(arr, cronType)
|
||||
return
|
||||
}
|
||||
|
||||
// 每月任务
|
||||
func (s *sSystemCron) monthlyTask() {
|
||||
if len(s.MonthlyTask) == 0 {
|
||||
return
|
||||
}
|
||||
s.AddFuncChan(s.MonthlyTask, v1.CronType_MONTH)
|
||||
return
|
||||
}
|
||||
|
||||
//每年任务
|
||||
func (s *sSystemCron) yearlyTask() {
|
||||
if len(s.YearlyTask) == 0 {
|
||||
return
|
||||
}
|
||||
s.AddFuncChan(s.YearlyTask, v1.CronType_YEAR)
|
||||
|
||||
}
|
||||
|
||||
// AddFuncChan 添加方法到通道
|
||||
func (s *sSystemCron) AddFuncChan(list []func(context.Context) error, cronType v1.CronType) {
|
||||
for _, v := range list {
|
||||
s.taskChan <- TaskWithParams{
|
||||
TaskFunc: v,
|
||||
CronType: cronType,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RunFuncChan 统一执行方法
|
||||
func (s *sSystemCron) RunFuncChan() {
|
||||
go func() {
|
||||
for task := range s.taskChan {
|
||||
//ctx := gctx.New()
|
||||
func() {
|
||||
//超时释放资源
|
||||
ctx, cancel := context.WithTimeout(gctx.New(), s.TaskTimeout)
|
||||
defer cancel()
|
||||
|
||||
// 使用匿名函数包裹来捕获 panic
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
g.Log().Errorf(gctx.New(), "执行函数时发生 panic: %v", r)
|
||||
}
|
||||
}()
|
||||
if task.CronType != v1.CronType_MINUTE && task.CronType != v1.CronType_SECOND {
|
||||
if runtime.FuncForPC(reflect.ValueOf(task.TaskFunc).Pointer()) != nil {
|
||||
g.Log().Debugf(gctx.New(), "开始执行任务: %v", runtime.FuncForPC(reflect.ValueOf(task.TaskFunc).Pointer()).Name())
|
||||
} else {
|
||||
g.Log().Debugf(gctx.New(), "开始执行任务: %v", "无法获取函数信息")
|
||||
}
|
||||
}
|
||||
|
||||
done := make(chan error)
|
||||
go func() {
|
||||
done <- task.TaskFunc(ctx)
|
||||
if task.CronType != v1.CronType_MINUTE && task.CronType != v1.CronType_SECOND {
|
||||
if runtime.FuncForPC(reflect.ValueOf(task.TaskFunc).Pointer()) != nil {
|
||||
g.Log().Debugf(gctx.New(), "结束执行任务: %v", runtime.FuncForPC(reflect.ValueOf(task.TaskFunc).Pointer()).Name())
|
||||
} else {
|
||||
g.Log().Debugf(gctx.New(), "结束执行任务: %v", "无法获取函数信息")
|
||||
}
|
||||
}
|
||||
}()
|
||||
//err := task()
|
||||
//if err != nil {
|
||||
// g.Log().Error(ctx, err)
|
||||
//}
|
||||
select {
|
||||
case taskErr := <-done:
|
||||
if taskErr != nil {
|
||||
// 使用新上下文记录错误
|
||||
g.Log().Error(gctx.New(), taskErr)
|
||||
}
|
||||
case <-ctx.Done(): // 监听上下文取消(包括超时)
|
||||
g.Log().Errorf(gctx.New(), "task timeout:%v", ctx.Err())
|
||||
}
|
||||
}()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// RunFunc 统一执行方法
|
||||
// deprecated: 弃用,会造成周期任务并发执行,to service.SystemCron().AddFuncChan
|
||||
func (s *sSystemCron) RunFunc(list []func() error) {
|
||||
for _, _func := range list {
|
||||
ctx := gctx.New()
|
||||
func() {
|
||||
// 使用匿名函数包裹来捕获 panic
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
g.Log().Errorf(ctx, "执行函数时发生 panic: %v", r)
|
||||
}
|
||||
}()
|
||||
err := _func()
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
return
|
||||
}
|
||||
67
internal/logic/systemLog/systemLog.go
Normal file
67
internal/logic/systemLog/systemLog.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package systemLog
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
v1 "github.com/ayflying/utility_go/api/admin/v1"
|
||||
"github.com/ayflying/utility_go/service"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
)
|
||||
|
||||
type sSystemLog struct {
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
var (
|
||||
ctx = gctx.New()
|
||||
//db = dao.AdminSystemLog.Ctx(ctx)
|
||||
name = "system_log"
|
||||
)
|
||||
|
||||
func init() {
|
||||
service.RegisterSystemLog(New())
|
||||
}
|
||||
|
||||
func New() *sSystemLog {
|
||||
return &sSystemLog{}
|
||||
}
|
||||
|
||||
func (s *sSystemLog) List(page int) (list []*v1.SystemLog, max int, err error) {
|
||||
|
||||
//var list = []*AdminSystemLog{}
|
||||
max, _ = g.Model(name).Count()
|
||||
g.Model(name).OrderDesc("created_at").Page(page, 100).Scan(&list)
|
||||
return
|
||||
}
|
||||
|
||||
// 写入操作日志
|
||||
func (s *sSystemLog) AddLog(uid int, url string, ip string, data g.Map) (id int64, err error) {
|
||||
//跳过空日志
|
||||
if data == nil {
|
||||
return
|
||||
}
|
||||
//如果存在这些值,直接跳过不写入日志
|
||||
paichu := []string{
|
||||
"/api/install",
|
||||
"/activity/url/log/add",
|
||||
"/system/update",
|
||||
"/api/cdkey",
|
||||
}
|
||||
|
||||
for _, item := range paichu {
|
||||
if item == url {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var post v1.SystemLog
|
||||
//uid := g.RequestFromCtx(ctx).Header.Get("x-uid")
|
||||
post.Uid = uid
|
||||
post.Url = url
|
||||
post.Ip = ip
|
||||
post.Data = data
|
||||
|
||||
id, err = g.Model(name).InsertAndGetId(post)
|
||||
return
|
||||
}
|
||||
18
internal/model/do/community_fans.go
Normal file
18
internal/model/do/community_fans.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// CommunityFans is the golang structure of table shiningu_community_fans for DAO operations like Where/Data.
|
||||
type CommunityFans struct {
|
||||
g.Meta `orm:"table:shiningu_community_fans, do:true"`
|
||||
Uid interface{} // 用户编号
|
||||
Fans interface{} // 粉丝编号
|
||||
CreatedAt *gtime.Time // 关注时间
|
||||
}
|
||||
19
internal/model/do/community_feeds.go
Normal file
19
internal/model/do/community_feeds.go
Normal file
@@ -0,0 +1,19 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// CommunityFeeds is the golang structure of table shiningu_community_feeds for DAO operations like Where/Data.
|
||||
type CommunityFeeds struct {
|
||||
g.Meta `orm:"table:shiningu_community_feeds, do:true"`
|
||||
Id interface{} // 流水
|
||||
Uid interface{} //
|
||||
PostId interface{} // 帖子编号
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
}
|
||||
23
internal/model/do/community_gift.go
Normal file
23
internal/model/do/community_gift.go
Normal file
@@ -0,0 +1,23 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// CommunityGift is the golang structure of table shiningu_community_gift for DAO operations like Where/Data.
|
||||
type CommunityGift struct {
|
||||
g.Meta `orm:"table:shiningu_community_gift, do:true"`
|
||||
Id interface{} //
|
||||
Uid interface{} // 收礼玩家编号
|
||||
FromUid interface{} // 送礼玩家编号
|
||||
Type interface{} // 送礼类型
|
||||
Pid interface{} // 帖子编号
|
||||
ItemId interface{} // 礼物编号
|
||||
Count interface{} // 礼物数量
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
}
|
||||
16
internal/model/do/community_menu.go
Normal file
16
internal/model/do/community_menu.go
Normal file
@@ -0,0 +1,16 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// CommunityMenu is the golang structure of table shiningu_community_menu for DAO operations like Where/Data.
|
||||
type CommunityMenu struct {
|
||||
g.Meta `orm:"table:shiningu_community_menu, do:true"`
|
||||
Id interface{} //
|
||||
Name interface{} // 栏目名称
|
||||
}
|
||||
25
internal/model/do/community_notice.go
Normal file
25
internal/model/do/community_notice.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// CommunityNotice is the golang structure of table shiningu_community_notice for DAO operations like Where/Data.
|
||||
type CommunityNotice struct {
|
||||
g.Meta `orm:"table:shiningu_community_notice, do:true"`
|
||||
Id interface{} //
|
||||
Uid interface{} // 用户编号
|
||||
FromUid interface{} // 对方用户编号
|
||||
Type interface{} // 类型
|
||||
Sid interface{} // 来源编号
|
||||
Content interface{} // 正文
|
||||
Extend interface{} // 附加属性
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
UpdatedAt *gtime.Time // 更新时间
|
||||
Status interface{} // 通知状态
|
||||
}
|
||||
38
internal/model/do/community_posts.go
Normal file
38
internal/model/do/community_posts.go
Normal file
@@ -0,0 +1,38 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// CommunityPosts is the golang structure of table shiningu_community_posts for DAO operations like Where/Data.
|
||||
type CommunityPosts struct {
|
||||
g.Meta `orm:"table:shiningu_community_posts, do:true"`
|
||||
Id interface{} // 帖子编号
|
||||
Tid interface{} // 帖子栏目
|
||||
Uid interface{} // 发布者
|
||||
Click interface{} // 点击数
|
||||
LikeCount interface{} // 点赞数量
|
||||
CollectCount interface{} // 收藏数量
|
||||
Popularity interface{} // 人气度热度
|
||||
Charm interface{} // 魅力值
|
||||
Language interface{} // 语言
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
UpdatedAt *gtime.Time // 更新时间
|
||||
DeletedAt *gtime.Time // 删除时间
|
||||
Topic1 interface{} // 话题1
|
||||
Topic2 interface{} // 话题2
|
||||
Status interface{} // 帖子状态 -1限流 0 正常
|
||||
Recommend interface{} // 小编推荐
|
||||
Extend interface{} // 附加信息
|
||||
At interface{} // 用户的at功能
|
||||
Period interface{} // 最新期数
|
||||
Price interface{} // 当前价格
|
||||
Index interface{} // 索引编号
|
||||
Gesture interface{} // 手势
|
||||
CharacterNum interface{} // 角色数量
|
||||
}
|
||||
28
internal/model/do/community_posts_0.go
Normal file
28
internal/model/do/community_posts_0.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// CommunityPosts0 is the golang structure of table shiningu_community_posts_0 for DAO operations like Where/Data.
|
||||
type CommunityPosts0 struct {
|
||||
g.Meta `orm:"table:shiningu_community_posts_0, do:true"`
|
||||
Id interface{} // 帖子编号
|
||||
Title interface{} // 标题
|
||||
Content interface{} // 帖子正文
|
||||
Images interface{} // 帖子图片批量
|
||||
Image interface{} // 图片
|
||||
ImagesRatio interface{} // 图片长宽比
|
||||
Like interface{} // 点赞
|
||||
Collect interface{} // 收藏
|
||||
Extend interface{} // 附加信息
|
||||
At interface{} // at
|
||||
Data interface{} // 内容属性
|
||||
UseIds interface{} // 最新期数
|
||||
Share interface{} // 分享帖子
|
||||
AiScore interface{} //
|
||||
}
|
||||
28
internal/model/do/community_posts_1.go
Normal file
28
internal/model/do/community_posts_1.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// CommunityPosts1 is the golang structure of table shiningu_community_posts_1 for DAO operations like Where/Data.
|
||||
type CommunityPosts1 struct {
|
||||
g.Meta `orm:"table:shiningu_community_posts_1, do:true"`
|
||||
Id interface{} // 帖子编号
|
||||
Title interface{} // 标题
|
||||
Content interface{} // 帖子正文
|
||||
Images interface{} // 帖子图片批量
|
||||
Image interface{} // 图片
|
||||
ImagesRatio interface{} // 图片长宽比
|
||||
Like interface{} // 点赞
|
||||
Collect interface{} // 收藏
|
||||
Extend interface{} // 附加信息
|
||||
At interface{} // at
|
||||
Data interface{} // 内容属性
|
||||
UseIds interface{} // 最新期数
|
||||
Share interface{} // 分享帖子
|
||||
AiScore interface{} //
|
||||
}
|
||||
17
internal/model/do/community_posts_details.go
Normal file
17
internal/model/do/community_posts_details.go
Normal file
@@ -0,0 +1,17 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// CommunityPostsDetails is the golang structure of table shiningu_community_posts_details for DAO operations like Where/Data.
|
||||
type CommunityPostsDetails struct {
|
||||
g.Meta `orm:"table:shiningu_community_posts_details, do:true"`
|
||||
Id interface{} //
|
||||
Attachment interface{} // 帖子附件
|
||||
SlotsImg interface{} // 槽位图片
|
||||
}
|
||||
17
internal/model/do/community_posts_hot_del.go
Normal file
17
internal/model/do/community_posts_hot_del.go
Normal file
@@ -0,0 +1,17 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// CommunityPostsHotDel is the golang structure of table shiningu_community_posts_hot_del for DAO operations like Where/Data.
|
||||
type CommunityPostsHotDel struct {
|
||||
g.Meta `orm:"table:shiningu_community_posts_hot_del, do:true"`
|
||||
Id interface{} // 帖子编号
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
}
|
||||
19
internal/model/do/community_posts_recommend.go
Normal file
19
internal/model/do/community_posts_recommend.go
Normal file
@@ -0,0 +1,19 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// CommunityPostsRecommend is the golang structure of table shiningu_community_posts_recommend for DAO operations like Where/Data.
|
||||
type CommunityPostsRecommend struct {
|
||||
g.Meta `orm:"table:shiningu_community_posts_recommend, do:true"`
|
||||
Pid interface{} // 帖子编号
|
||||
Type interface{} // 推荐类型
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
EndTime *gtime.Time // 结束时间
|
||||
}
|
||||
28
internal/model/do/community_posts_reply.go
Normal file
28
internal/model/do/community_posts_reply.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// CommunityPostsReply is the golang structure of table shiningu_community_posts_reply for DAO operations like Where/Data.
|
||||
type CommunityPostsReply struct {
|
||||
g.Meta `orm:"table:shiningu_community_posts_reply, do:true"`
|
||||
Id interface{} // 唯一id
|
||||
Pid interface{} // 主贴id
|
||||
Uid interface{} //
|
||||
Uid2 interface{} // 被回复者的uid
|
||||
Content interface{} // 正文
|
||||
Extend interface{} // 附加数据
|
||||
TopId interface{} // 上级id
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
Sort interface{} // 跟帖顺序
|
||||
AiScore interface{} // 机器评分
|
||||
Status interface{} // 状态
|
||||
At interface{} // 用户的at功能
|
||||
Like interface{} // 回复点赞
|
||||
}
|
||||
22
internal/model/do/community_user.go
Normal file
22
internal/model/do/community_user.go
Normal file
@@ -0,0 +1,22 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// CommunityUser is the golang structure of table shiningu_community_user for DAO operations like Where/Data.
|
||||
type CommunityUser struct {
|
||||
g.Meta `orm:"table:shiningu_community_user, do:true"`
|
||||
Uid interface{} //
|
||||
Like interface{} // 点赞
|
||||
Like2 interface{} // 帖子回复点赞
|
||||
Collect interface{} // 收藏
|
||||
FollowNum interface{} // 关注数量
|
||||
FansNum interface{} // 粉丝数量
|
||||
Gift interface{} // 礼物值
|
||||
Blacklist interface{} // 黑名单
|
||||
}
|
||||
25
internal/model/do/config_act.go
Normal file
25
internal/model/do/config_act.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// ConfigAct is the golang structure of table shiningu_config_act for DAO operations like Where/Data.
|
||||
type ConfigAct struct {
|
||||
g.Meta `orm:"table:shiningu_config_act, do:true"`
|
||||
Id interface{} // 流水编号
|
||||
Type interface{} // 活动类型
|
||||
Actid interface{} // 活动编号
|
||||
Name interface{} // 活动名称
|
||||
Hid interface{} // 活动标识
|
||||
Data interface{} // 活动数据
|
||||
StartTime *gtime.Time // 开始时间
|
||||
EndTime *gtime.Time // 结束时间
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
UpdatedAt *gtime.Time // 更新时间
|
||||
}
|
||||
32
internal/model/do/config_modal_box.go
Normal file
32
internal/model/do/config_modal_box.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// ConfigModalBox is the golang structure of table shiningu_config_modal_box for DAO operations like Where/Data.
|
||||
type ConfigModalBox struct {
|
||||
g.Meta `orm:"table:shiningu_config_modal_box, do:true"`
|
||||
Id interface{} // 主键
|
||||
ModalBoxId interface{} // 弹框id
|
||||
UserType interface{} // 特定用户
|
||||
Tips interface{} // 弹框tips选项
|
||||
Name interface{} // 名称
|
||||
Title interface{} // 标题
|
||||
Content interface{} // 正文
|
||||
Type interface{} // 类型
|
||||
Style interface{} // 样式
|
||||
Weight interface{} // 权重
|
||||
Attachments interface{} // 附件
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
UpdatedAt *gtime.Time // 更新时间
|
||||
Status interface{} // 状态 1开始 0关闭
|
||||
Notes interface{} // 备注
|
||||
StartTime *gtime.Time // 开始时间
|
||||
EndTime *gtime.Time // 结束时间
|
||||
}
|
||||
19
internal/model/do/game_act.go
Normal file
19
internal/model/do/game_act.go
Normal file
@@ -0,0 +1,19 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// GameAct is the golang structure of table shiningu_game_act for DAO operations like Where/Data.
|
||||
type GameAct struct {
|
||||
g.Meta `orm:"table:shiningu_game_act, do:true"`
|
||||
Uid interface{} // 玩家编号
|
||||
ActId interface{} // 活动编号
|
||||
Action interface{} // 活动配置
|
||||
UpdatedAt *gtime.Time // 更新时间
|
||||
}
|
||||
18
internal/model/do/game_bag.go
Normal file
18
internal/model/do/game_bag.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// GameBag is the golang structure of table shiningu_game_bag for DAO operations like Where/Data.
|
||||
type GameBag struct {
|
||||
g.Meta `orm:"table:shiningu_game_bag, do:true"`
|
||||
Uid interface{} // 用户标识
|
||||
List interface{} // 道具数据
|
||||
Book interface{} // 图鉴
|
||||
Hand interface{} // 手势
|
||||
}
|
||||
19
internal/model/do/game_config.go
Normal file
19
internal/model/do/game_config.go
Normal file
@@ -0,0 +1,19 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// GameConfig is the golang structure of table shiningu_game_config for DAO operations like Where/Data.
|
||||
type GameConfig struct {
|
||||
g.Meta `orm:"table:shiningu_game_config, do:true"`
|
||||
Name interface{} // 配置名称
|
||||
Data interface{} // 配置内容
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
UpdatedAt *gtime.Time // 更新时间
|
||||
}
|
||||
18
internal/model/do/game_kv.go
Normal file
18
internal/model/do/game_kv.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// GameKv is the golang structure of table shiningu_game_kv for DAO operations like Where/Data.
|
||||
type GameKv struct {
|
||||
g.Meta `orm:"table:shiningu_game_kv, do:true"`
|
||||
Uid interface{} // 用户
|
||||
Kv interface{} // 变量
|
||||
UpdatedAt *gtime.Time // 更新时间
|
||||
}
|
||||
27
internal/model/do/game_mail.go
Normal file
27
internal/model/do/game_mail.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// GameMail is the golang structure of table shiningu_game_mail for DAO operations like Where/Data.
|
||||
type GameMail struct {
|
||||
g.Meta `orm:"table:shiningu_game_mail, do:true"`
|
||||
Id interface{} // 流水
|
||||
Uid interface{} // 用户标识
|
||||
Type interface{} // 类型
|
||||
Title interface{} // 标题
|
||||
Content interface{} // 正文
|
||||
Items interface{} // 奖励道具
|
||||
HaveItems interface{} // 是否有附件
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
Sign interface{} // 署名
|
||||
EndTime *gtime.Time // 结束时间
|
||||
Extend interface{} // 附加参数
|
||||
Status interface{} // 状态
|
||||
}
|
||||
23
internal/model/do/game_mail_mass.go
Normal file
23
internal/model/do/game_mail_mass.go
Normal file
@@ -0,0 +1,23 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// GameMailMass is the golang structure of table shiningu_game_mail_mass for DAO operations like Where/Data.
|
||||
type GameMailMass struct {
|
||||
g.Meta `orm:"table:shiningu_game_mail_mass, do:true"`
|
||||
Id interface{} // 主键
|
||||
Title interface{} // 标题
|
||||
Type interface{} // 类型
|
||||
Content interface{} // 正文
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
Items interface{} // 奖励
|
||||
Sign interface{} // 署名
|
||||
EndTime *gtime.Time // 结束时间
|
||||
}
|
||||
16
internal/model/do/game_mail_user.go
Normal file
16
internal/model/do/game_mail_user.go
Normal file
@@ -0,0 +1,16 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// GameMailUser is the golang structure of table shiningu_game_mail_user for DAO operations like Where/Data.
|
||||
type GameMailUser struct {
|
||||
g.Meta `orm:"table:shiningu_game_mail_user, do:true"`
|
||||
Uid interface{} //
|
||||
Mass interface{} // 群发邮件领取列表
|
||||
}
|
||||
29
internal/model/do/game_pay.go
Normal file
29
internal/model/do/game_pay.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// GamePay is the golang structure of table shiningu_game_pay for DAO operations like Where/Data.
|
||||
type GamePay struct {
|
||||
g.Meta `orm:"table:shiningu_game_pay, do:true"`
|
||||
OrderId interface{} // 订单编号
|
||||
Uid interface{} //
|
||||
TerraceOrderId interface{} // 平台订单id
|
||||
Device interface{} // 设备名称
|
||||
Channel interface{} // 支付渠道
|
||||
ShopId interface{} // 商品id
|
||||
Cent interface{} // 美分(不要使用小数点)
|
||||
PackageName interface{} // 包名
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
UpdatedAt *gtime.Time // 更新时间
|
||||
PayTime *gtime.Time // 支付时间
|
||||
Status interface{} // 状态
|
||||
Token interface{} // 支付标识
|
||||
Ip interface{} // ip地址
|
||||
}
|
||||
25
internal/model/do/game_rank.go
Normal file
25
internal/model/do/game_rank.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// GameRank is the golang structure of table shiningu_game_rank for DAO operations like Where/Data.
|
||||
type GameRank struct {
|
||||
g.Meta `orm:"table:shiningu_game_rank, do:true"`
|
||||
Key interface{} //
|
||||
RankId interface{} // 排行榜编号
|
||||
Type interface{} // 排行榜类型
|
||||
Data interface{} // 数据
|
||||
CreatedAt *gtime.Time // 排行榜创建时间
|
||||
StartTime *gtime.Time // 榜单开始时间
|
||||
EndTime *gtime.Time // 榜单结束时间
|
||||
Status interface{} //
|
||||
Image interface{} // 结算封面
|
||||
FirstUid interface{} // 第一名的用户id
|
||||
}
|
||||
20
internal/model/do/game_stage.go
Normal file
20
internal/model/do/game_stage.go
Normal file
@@ -0,0 +1,20 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// GameStage is the golang structure of table shiningu_game_stage for DAO operations like Where/Data.
|
||||
type GameStage struct {
|
||||
g.Meta `orm:"table:shiningu_game_stage, do:true"`
|
||||
Uid interface{} // 用户标识
|
||||
Chapter interface{} // 章节
|
||||
WinData interface{} // 通关过的数据
|
||||
StageData interface{} // 关卡数据
|
||||
Star interface{} // 章节获得的总星
|
||||
RwdData interface{} // 通关奖励领取
|
||||
}
|
||||
21
internal/model/do/member_authorize.go
Normal file
21
internal/model/do/member_authorize.go
Normal file
@@ -0,0 +1,21 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// MemberAuthorize is the golang structure of table shiningu_member_authorize for DAO operations like Where/Data.
|
||||
type MemberAuthorize struct {
|
||||
g.Meta `orm:"table:shiningu_member_authorize, do:true"`
|
||||
Code interface{} // 授权码
|
||||
Uid interface{} // 用户标识
|
||||
Type interface{} // 认证方式
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
UpdatedAt *gtime.Time // 更新时间
|
||||
CreateIp interface{} // 创建ip
|
||||
}
|
||||
18
internal/model/do/member_ban.go
Normal file
18
internal/model/do/member_ban.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// MemberBan is the golang structure of table shiningu_member_ban for DAO operations like Where/Data.
|
||||
type MemberBan struct {
|
||||
g.Meta `orm:"table:shiningu_member_ban, do:true"`
|
||||
Uid interface{} // 用户编号
|
||||
CreatedAt *gtime.Time // 禁用时间
|
||||
Type interface{} // 禁用类型
|
||||
}
|
||||
18
internal/model/do/member_friend.go
Normal file
18
internal/model/do/member_friend.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// MemberFriend is the golang structure of table shiningu_member_friend for DAO operations like Where/Data.
|
||||
type MemberFriend struct {
|
||||
g.Meta `orm:"table:shiningu_member_friend, do:true"`
|
||||
Uid interface{} // 当前用户
|
||||
Uid2 interface{} // 对方编号
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
}
|
||||
18
internal/model/do/member_limit.go
Normal file
18
internal/model/do/member_limit.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// MemberLimit is the golang structure of table shiningu_member_limit for DAO operations like Where/Data.
|
||||
type MemberLimit struct {
|
||||
g.Meta `orm:"table:shiningu_member_limit, do:true"`
|
||||
Uid interface{} // 用户uid
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
Data interface{} // 玩家权限
|
||||
}
|
||||
24
internal/model/do/member_save.go
Normal file
24
internal/model/do/member_save.go
Normal file
@@ -0,0 +1,24 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// MemberSave is the golang structure of table shiningu_member_save for DAO operations like Where/Data.
|
||||
type MemberSave struct {
|
||||
g.Meta `orm:"table:shiningu_member_save, do:true"`
|
||||
Uid interface{} // 用户编号
|
||||
Type interface{} // 存档类型
|
||||
Slot interface{} // 存档槽位
|
||||
Data interface{} // 存档内容
|
||||
S3 interface{} // s3地址
|
||||
UpdatedAt *gtime.Time // 更新时间
|
||||
Name interface{} // 自定义名字
|
||||
Image interface{} // 上传图片
|
||||
UseIds interface{} // 使用的道具id
|
||||
}
|
||||
42
internal/model/do/member_user.go
Normal file
42
internal/model/do/member_user.go
Normal file
@@ -0,0 +1,42 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// MemberUser is the golang structure of table shiningu_member_user for DAO operations like Where/Data.
|
||||
type MemberUser struct {
|
||||
g.Meta `orm:"table:shiningu_member_user, do:true"`
|
||||
Uid interface{} // 用户标识
|
||||
Guid interface{} // 用户本次登录标识
|
||||
Gid interface{} // 用户组编号
|
||||
AccountLogin interface{} // 社交账号登录
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
UpdatedAt *gtime.Time // 更新时间
|
||||
DeletedAt *gtime.Time // 删除时间
|
||||
Nickname interface{} // 昵称
|
||||
Phone interface{} // 绑定手机
|
||||
Email interface{} // 绑定邮箱
|
||||
Money interface{} // 充值货币
|
||||
Save interface{} // 储存路径
|
||||
Slots interface{} // 槽位数量
|
||||
OnlineDuration interface{} // 在线时长
|
||||
OnlineStatus interface{} // 在线状态
|
||||
OnlineTime *gtime.Time // 上线时间
|
||||
OfflineTime *gtime.Time // 离线时间
|
||||
CreateIp interface{} // 创号ip地址
|
||||
UpdateIp interface{} // 更新IP地址
|
||||
Level interface{} // 等级
|
||||
Exp interface{} // 经验
|
||||
Title interface{} // 称号
|
||||
Avatar interface{} // 头像
|
||||
AvatarFrame interface{} // 头像框
|
||||
Popularity interface{} // 人气度
|
||||
Charm interface{} // 魅力值
|
||||
Gift interface{} // 礼物值
|
||||
}
|
||||
15
internal/model/do/system_cron.go
Normal file
15
internal/model/do/system_cron.go
Normal file
@@ -0,0 +1,15 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// SystemCron is the golang structure of table shiningu_system_cron for DAO operations like Where/Data.
|
||||
type SystemCron struct {
|
||||
g.Meta `orm:"table:shiningu_system_cron, do:true"`
|
||||
Id interface{} // 编号
|
||||
}
|
||||
21
internal/model/do/system_log.go
Normal file
21
internal/model/do/system_log.go
Normal file
@@ -0,0 +1,21 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// SystemLog is the golang structure of table shiningu_system_log for DAO operations like Where/Data.
|
||||
type SystemLog struct {
|
||||
g.Meta `orm:"table:shiningu_system_log, do:true"`
|
||||
Id interface{} // 主键
|
||||
Uid interface{} // 操作的用户
|
||||
Url interface{} // 当前访问的url
|
||||
Data interface{} // 操作数据
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
Ip interface{} // 当前ip地址
|
||||
}
|
||||
23
internal/model/do/system_report.go
Normal file
23
internal/model/do/system_report.go
Normal file
@@ -0,0 +1,23 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// SystemReport is the golang structure of table shiningu_system_report for DAO operations like Where/Data.
|
||||
type SystemReport struct {
|
||||
g.Meta `orm:"table:shiningu_system_report, do:true"`
|
||||
Id interface{} //
|
||||
Rid interface{} // 举报id
|
||||
Uid interface{} // 举报人编号
|
||||
Type interface{} // 举报类型
|
||||
Desc interface{} // 举报正文
|
||||
CreatedAt *gtime.Time // 举报时间
|
||||
DeletedAt *gtime.Time // 删除时间
|
||||
Status interface{} // 处理状态
|
||||
}
|
||||
17
internal/model/do/system_setting.go
Normal file
17
internal/model/do/system_setting.go
Normal file
@@ -0,0 +1,17 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// SystemSetting is the golang structure of table shiningu_system_setting for DAO operations like Where/Data.
|
||||
type SystemSetting struct {
|
||||
g.Meta `orm:"table:shiningu_system_setting, do:true"`
|
||||
Name interface{} // 配置名称
|
||||
Value interface{} // 配置详情
|
||||
Type interface{} // 类型
|
||||
}
|
||||
18
internal/model/do/system_statistics.go
Normal file
18
internal/model/do/system_statistics.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// SystemStatistics is the golang structure of table shiningu_system_statistics for DAO operations like Where/Data.
|
||||
type SystemStatistics struct {
|
||||
g.Meta `orm:"table:shiningu_system_statistics, do:true"`
|
||||
Id interface{} // 流水号
|
||||
AppId interface{} // 应用编号
|
||||
Key interface{} // 唯一缓存key
|
||||
Data interface{} // 数据
|
||||
}
|
||||
16
internal/model/entity/community_fans.go
Normal file
16
internal/model/entity/community_fans.go
Normal file
@@ -0,0 +1,16 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package entity
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// CommunityFans is the golang structure for table community_fans.
|
||||
type CommunityFans struct {
|
||||
Uid int64 `json:"uid" orm:"uid" description:"用户编号"` // 用户编号
|
||||
Fans int64 `json:"fans" orm:"fans" description:"粉丝编号"` // 粉丝编号
|
||||
CreatedAt *gtime.Time `json:"created_at" orm:"created_at" description:"关注时间"` // 关注时间
|
||||
}
|
||||
17
internal/model/entity/community_feeds.go
Normal file
17
internal/model/entity/community_feeds.go
Normal file
@@ -0,0 +1,17 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package entity
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// CommunityFeeds is the golang structure for table community_feeds.
|
||||
type CommunityFeeds struct {
|
||||
Id int `json:"id" orm:"id" description:"流水"` // 流水
|
||||
Uid int64 `json:"uid" orm:"uid" description:""` //
|
||||
PostId int `json:"post_id" orm:"post_id" description:"帖子编号"` // 帖子编号
|
||||
CreatedAt *gtime.Time `json:"created_at" orm:"created_at" description:"创建时间"` // 创建时间
|
||||
}
|
||||
21
internal/model/entity/community_gift.go
Normal file
21
internal/model/entity/community_gift.go
Normal file
@@ -0,0 +1,21 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package entity
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// CommunityGift is the golang structure for table community_gift.
|
||||
type CommunityGift struct {
|
||||
Id int `json:"id" orm:"id" description:""` //
|
||||
Uid int64 `json:"uid" orm:"uid" description:"收礼玩家编号"` // 收礼玩家编号
|
||||
FromUid int64 `json:"from_uid" orm:"fromUid" description:"送礼玩家编号"` // 送礼玩家编号
|
||||
Type int `json:"type" orm:"type" description:"送礼类型"` // 送礼类型
|
||||
Pid int `json:"pid" orm:"pid" description:"帖子编号"` // 帖子编号
|
||||
ItemId int64 `json:"item_id" orm:"itemId" description:"礼物编号"` // 礼物编号
|
||||
Count int `json:"count" orm:"count" description:"礼物数量"` // 礼物数量
|
||||
CreatedAt *gtime.Time `json:"created_at" orm:"created_at" description:"创建时间"` // 创建时间
|
||||
}
|
||||
11
internal/model/entity/community_menu.go
Normal file
11
internal/model/entity/community_menu.go
Normal file
@@ -0,0 +1,11 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package entity
|
||||
|
||||
// CommunityMenu is the golang structure for table community_menu.
|
||||
type CommunityMenu struct {
|
||||
Id int `json:"id" orm:"id" description:""` //
|
||||
Name string `json:"name" orm:"name" description:"栏目名称"` // 栏目名称
|
||||
}
|
||||
23
internal/model/entity/community_notice.go
Normal file
23
internal/model/entity/community_notice.go
Normal file
@@ -0,0 +1,23 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package entity
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// CommunityNotice is the golang structure for table community_notice.
|
||||
type CommunityNotice struct {
|
||||
Id int `json:"id" orm:"id" description:""` //
|
||||
Uid int64 `json:"uid" orm:"uid" description:"用户编号"` // 用户编号
|
||||
FromUid int64 `json:"from_uid" orm:"from_uid" description:"对方用户编号"` // 对方用户编号
|
||||
Type int `json:"type" orm:"type" description:"类型"` // 类型
|
||||
Sid int `json:"sid" orm:"sid" description:"来源编号"` // 来源编号
|
||||
Content string `json:"content" orm:"content" description:"正文"` // 正文
|
||||
Extend string `json:"extend" orm:"extend" description:"附加属性"` // 附加属性
|
||||
CreatedAt *gtime.Time `json:"created_at" orm:"created_at" description:"创建时间"` // 创建时间
|
||||
UpdatedAt *gtime.Time `json:"updated_at" orm:"updated_at" description:"更新时间"` // 更新时间
|
||||
Status int `json:"status" orm:"status" description:"通知状态"` // 通知状态
|
||||
}
|
||||
36
internal/model/entity/community_posts.go
Normal file
36
internal/model/entity/community_posts.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package entity
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// CommunityPosts is the golang structure for table community_posts.
|
||||
type CommunityPosts struct {
|
||||
Id int `json:"id" orm:"id" description:"帖子编号"` // 帖子编号
|
||||
Tid int `json:"tid" orm:"tid" description:"帖子栏目"` // 帖子栏目
|
||||
Uid int64 `json:"uid" orm:"uid" description:"发布者"` // 发布者
|
||||
Click int64 `json:"click" orm:"click" description:"点击数"` // 点击数
|
||||
LikeCount int `json:"like_count" orm:"like_count" description:"点赞数量"` // 点赞数量
|
||||
CollectCount int `json:"collect_count" orm:"collect_count" description:"收藏数量"` // 收藏数量
|
||||
Popularity int `json:"popularity" orm:"popularity" description:"人气度热度"` // 人气度热度
|
||||
Charm int `json:"charm" orm:"charm" description:"魅力值"` // 魅力值
|
||||
Language string `json:"language" orm:"language" description:"语言"` // 语言
|
||||
CreatedAt *gtime.Time `json:"created_at" orm:"created_at" description:"创建时间"` // 创建时间
|
||||
UpdatedAt *gtime.Time `json:"updated_at" orm:"updated_at" description:"更新时间"` // 更新时间
|
||||
DeletedAt *gtime.Time `json:"deleted_at" orm:"deleted_at" description:"删除时间"` // 删除时间
|
||||
Topic1 int `json:"topic_1" orm:"topic1" description:"话题1"` // 话题1
|
||||
Topic2 int `json:"topic_2" orm:"topic2" description:"话题2"` // 话题2
|
||||
Status int `json:"status" orm:"status" description:"帖子状态 -1限流 0 正常"` // 帖子状态 -1限流 0 正常
|
||||
Recommend int `json:"recommend" orm:"recommend" description:"小编推荐"` // 小编推荐
|
||||
Extend string `json:"extend" orm:"extend" description:"附加信息"` // 附加信息
|
||||
At string `json:"at" orm:"at" description:"用户的at功能"` // 用户的at功能
|
||||
Period int `json:"period" orm:"period" description:"最新期数"` // 最新期数
|
||||
Price int `json:"price" orm:"price" description:"当前价格"` // 当前价格
|
||||
Index int `json:"index" orm:"index" description:"索引编号"` // 索引编号
|
||||
Gesture int `json:"gesture" orm:"gesture" description:"手势"` // 手势
|
||||
CharacterNum int `json:"character_num" orm:"character_num" description:"角色数量"` // 角色数量
|
||||
}
|
||||
23
internal/model/entity/community_posts_0.go
Normal file
23
internal/model/entity/community_posts_0.go
Normal file
@@ -0,0 +1,23 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package entity
|
||||
|
||||
// CommunityPosts0 is the golang structure for table community_posts_0.
|
||||
type CommunityPosts0 struct {
|
||||
Id int `json:"id" orm:"id" description:"帖子编号"` // 帖子编号
|
||||
Title string `json:"title" orm:"title" description:"标题"` // 标题
|
||||
Content string `json:"content" orm:"content" description:"帖子正文"` // 帖子正文
|
||||
Images string `json:"images" orm:"images" description:"帖子图片批量"` // 帖子图片批量
|
||||
Image string `json:"image" orm:"image" description:"图片"` // 图片
|
||||
ImagesRatio string `json:"images_ratio" orm:"images_ratio" description:"图片长宽比"` // 图片长宽比
|
||||
Like string `json:"like" orm:"like" description:"点赞"` // 点赞
|
||||
Collect string `json:"collect" orm:"collect" description:"收藏"` // 收藏
|
||||
Extend string `json:"extend" orm:"extend" description:"附加信息"` // 附加信息
|
||||
At string `json:"at" orm:"at" description:"at"` // at
|
||||
Data string `json:"data" orm:"data" description:"内容属性"` // 内容属性
|
||||
UseIds string `json:"use_ids" orm:"use_ids" description:"最新期数"` // 最新期数
|
||||
Share string `json:"share" orm:"share" description:"分享帖子"` // 分享帖子
|
||||
AiScore int `json:"ai_score" orm:"ai_score" description:""` //
|
||||
}
|
||||
23
internal/model/entity/community_posts_1.go
Normal file
23
internal/model/entity/community_posts_1.go
Normal file
@@ -0,0 +1,23 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package entity
|
||||
|
||||
// CommunityPosts1 is the golang structure for table community_posts_1.
|
||||
type CommunityPosts1 struct {
|
||||
Id int `json:"id" orm:"id" description:"帖子编号"` // 帖子编号
|
||||
Title string `json:"title" orm:"title" description:"标题"` // 标题
|
||||
Content string `json:"content" orm:"content" description:"帖子正文"` // 帖子正文
|
||||
Images string `json:"images" orm:"images" description:"帖子图片批量"` // 帖子图片批量
|
||||
Image string `json:"image" orm:"image" description:"图片"` // 图片
|
||||
ImagesRatio string `json:"images_ratio" orm:"images_ratio" description:"图片长宽比"` // 图片长宽比
|
||||
Like string `json:"like" orm:"like" description:"点赞"` // 点赞
|
||||
Collect string `json:"collect" orm:"collect" description:"收藏"` // 收藏
|
||||
Extend string `json:"extend" orm:"extend" description:"附加信息"` // 附加信息
|
||||
At string `json:"at" orm:"at" description:"at"` // at
|
||||
Data string `json:"data" orm:"data" description:"内容属性"` // 内容属性
|
||||
UseIds string `json:"use_ids" orm:"use_ids" description:"最新期数"` // 最新期数
|
||||
Share string `json:"share" orm:"share" description:"分享帖子"` // 分享帖子
|
||||
AiScore int `json:"ai_score" orm:"ai_score" description:""` //
|
||||
}
|
||||
12
internal/model/entity/community_posts_details.go
Normal file
12
internal/model/entity/community_posts_details.go
Normal file
@@ -0,0 +1,12 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package entity
|
||||
|
||||
// CommunityPostsDetails is the golang structure for table community_posts_details.
|
||||
type CommunityPostsDetails struct {
|
||||
Id int `json:"id" orm:"id" description:""` //
|
||||
Attachment string `json:"attachment" orm:"attachment" description:"帖子附件"` // 帖子附件
|
||||
SlotsImg string `json:"slots_img" orm:"slots_img" description:"槽位图片"` // 槽位图片
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user