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
|
module github.com/ayflying/utility_go
|
||||||
|
|
||||||
go 1.23.0
|
go 1.24.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ayflying/excel2json v1.1.2
|
github.com/apolloconfig/agollo/v4 v4.4.0
|
||||||
github.com/gogf/gf/v2 v2.8.3
|
github.com/ayflying/excel2json v1.1.9
|
||||||
github.com/minio/minio-go/v7 v7.0.82
|
github.com/casdoor/casdoor-go-sdk v1.39.0
|
||||||
github.com/xuri/excelize/v2 v2.9.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 (
|
require (
|
||||||
github.com/360EntSecGroup-Skylar/excelize v1.4.1 // indirect
|
cloud.google.com/go/auth v0.17.0 // indirect
|
||||||
github.com/BurntSushi/toml v1.4.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/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/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/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-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/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/goccy/go-json v0.10.3 // indirect
|
github.com/go-pay/errgroup v0.0.3 // indirect
|
||||||
github.com/google/uuid v1.6.0 // 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/gorilla/websocket v1.5.3 // indirect
|
||||||
github.com/grokify/html-strip-tags-go v0.1.0 // indirect
|
github.com/grokify/html-strip-tags-go v0.1.0 // indirect
|
||||||
github.com/klauspost/compress v1.17.11 // indirect
|
github.com/hashicorp/go-hclog v1.5.0 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||||
github.com/magiconair/properties v1.8.9 // indirect
|
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // 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-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/minio/md5-simd v1.1.2 // indirect
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/olekukonko/tablewriter v0.0.5 // 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/mscfb v1.0.4 // indirect
|
||||||
github.com/richardlehane/msoleps 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/rs/xid v1.6.0 // indirect
|
||||||
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect
|
github.com/sagikazarmark/locafero v0.12.0 // indirect
|
||||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
|
github.com/spf13/afero v1.15.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
github.com/spf13/cast v1.10.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
github.com/spf13/pflag v1.0.10 // indirect
|
||||||
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
|
github.com/spf13/viper v1.21.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
golang.org/x/crypto v0.30.0 // indirect
|
github.com/tiendc/go-deepcopy v1.7.2 // indirect
|
||||||
golang.org/x/net v0.32.0 // indirect
|
github.com/tinylib/msgp v1.6.1 // indirect
|
||||||
golang.org/x/sys v0.28.0 // indirect
|
github.com/xuri/efp v0.0.1 // indirect
|
||||||
golang.org/x/text v0.21.0 // 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
|
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