同步代码

This commit is contained in:
hahwu 2025-01-09 10:33:13 +08:00
commit eadb5d5471
21 changed files with 21785 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.exe
release/*.tar

46
conf/server.yml Normal file
View File

@ -0,0 +1,46 @@
mysqls:
- host: '127.0.0.1'
name: 'merge_pet_test'
port: 3306
user: 'root'
password: 'Z4rf7eZZe500dxa'
database: 'pet_home_1'
idleTimeout: Infinity
- host: '127.0.0.1'
name: 'merge_pet_sdk'
port: 3306
user: 'root'
password: 'Z4rf7eZZe500dxa'
database: 'Merge_Pet_sdk'
idleTimeout: Infinity
- host: '127.0.0.1'
name: 'merge_pet_online'
port: 3306
user: 'root'
password: 'Xijing1!'
database: 'merge_pet_1'
idleTimeout: Infinity
- host: 'rm-f8zd2030feam53n43.mysql.rds.aliyuncs.com'
name: 'log'
port: 3306
user: 'root'
password: 'Z4rf7eZZe500dxa'
database: 'game'
idleTimeout: Infinity
servers:
- name: 'server1'
host: '1.15.182.107'
port: 22
username: 'root'
password: '`NS?VGg@7]~F3}p'
- name: 'server2'
host: '47.254.83.25'
port: 22
username: 'root'
password: 'ByWayStudios01!'
- name: 'log'
host: '8.155.14.94'
port: 22
username: 'root'
password: '-xLX]p!PQ1@SHm`A'

23
controller/auth.go Normal file
View File

@ -0,0 +1,23 @@
package controller
import "github.com/gin-gonic/gin"
func Login(c *gin.Context) {
c.JSON(200, gin.H{
"code": 0,
"data": map[string]interface{}{
"accessToken": "fakeToken",
},
"message": "Login success!",
})
}
func Codes(c *gin.Context) {
c.JSON(200, gin.H{
"code": 0,
"data": map[string]interface{}{
"codes": []string{"AC_100100", "AC_100110", "AC_100120", "AC_100010"},
},
"message": "Success",
})
}

18
controller/common.go Normal file
View File

@ -0,0 +1,18 @@
package controller
import "github.com/gin-gonic/gin"
func success(c *gin.Context, data interface{}) {
c.JSON(200, gin.H{
"code": 0,
"data": data,
"message": "Success",
})
}
func failed(c *gin.Context, message string) {
c.JSON(400, gin.H{
"code": 1,
"message": message,
})
}

52
controller/log.go Normal file
View File

@ -0,0 +1,52 @@
package controller
import (
"backend/model"
"github.com/gin-gonic/gin"
)
func Asset(c *gin.Context) {
log := model.Log{}
err := c.BindJSON(&log)
if err != nil {
failed(c, err.Error())
return
}
res, err := log.Asset()
if err != nil {
failed(c, err.Error())
return
}
success(c, res)
}
func Event(c *gin.Context) {
log := model.Log{}
err := c.BindJSON(&log)
if err != nil {
failed(c, err.Error())
return
}
res, err := log.Event()
if err != nil {
failed(c, err.Error())
return
}
success(c, res)
}
func Order(c *gin.Context) {
log := model.Log{}
err := c.BindJSON(&log)
if err != nil {
failed(c, err.Error())
return
}
res, err := log.Order()
if err != nil {
failed(c, err.Error())
return
}
success(c, res)
}

66
controller/user.go Normal file
View File

@ -0,0 +1,66 @@
package controller
import (
"backend/model"
"fmt"
"github.com/gin-gonic/gin"
)
func UserInfo(c *gin.Context) {
c.JSON(200, gin.H{
"code": 0,
"data": map[string]interface{}{
"id": 0,
"realName": "Vben",
"roles": []string{"super"},
"username": "vben",
},
"message": "Hello, world!",
})
}
func UserList(c *gin.Context) {
var request struct {
Id int `json:"Id"`
PageSize int `json:"pageSize"`
CurrentPage int `json:"currentPage"`
}
err := c.BindJSON(&request)
if err != nil {
fmt.Print(err)
failed(c, err.Error())
return
}
user, total, err := model.GetUserList(request.Id, request.PageSize, request.CurrentPage)
if err != nil {
fmt.Print(err)
failed(c, err.Error())
return
}
success(c, map[string]interface{}{
"total": total,
"data": user,
})
}
func UserDetail(c *gin.Context) {
var request struct {
Uid int `json:"Id"`
}
err := c.BindJSON(&request)
if err != nil {
fmt.Print(err)
failed(c, err.Error())
return
}
user, err := model.UserDetail(request.Uid)
if err != nil {
fmt.Print(err)
failed(c, err.Error())
return
}
success(c, user)
}

40
go.mod Normal file
View File

@ -0,0 +1,40 @@
module backend
go 1.23.1
require (
github.com/gin-gonic/gin v1.10.0
github.com/go-sql-driver/mysql v1.8.1
github.com/jmoiron/sqlx v1.4.0
golang.org/x/crypto v0.23.0
golang.org/x/net v0.25.0
google.golang.org/protobuf v1.34.1
gopkg.in/yaml.v2 v2.4.0
)
require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

103
go.sum Normal file
View File

@ -0,0 +1,103 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

27
main.go Normal file
View File

@ -0,0 +1,27 @@
package main
import (
"backend/controller"
"github.com/gin-gonic/gin"
)
// GOOS=linux GOARCH=amd64 go build -o /data/backend/release/backend main.go
func main() {
r := gin.Default()
api := r.Group("/api")
{
api.GET("/user/info", controller.UserInfo)
api.POST("/auth/login", controller.Login)
api.POST("/user/list", controller.UserList)
api.POST("/log/user", controller.UserDetail)
api.POST("/log/asset", controller.Asset)
api.POST("/log/event", controller.Event)
api.POST("/log/order", controller.Order)
api.GET("/auth/codes", controller.Codes)
}
r.Run(":5320") // 在 0.0.0.0:5320 上监听并服务
}

147
model/Mysql.go Normal file
View File

@ -0,0 +1,147 @@
package model
import (
"context"
"fmt"
"net"
"github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
"golang.org/x/crypto/ssh"
)
var MysqlList map[string]*sqlx.DB
func init() {
// // 初始化数据库
MysqlList = make(map[string]*sqlx.DB)
}
func connectToMySQLViaSSH(ServerName, MysqlName string) (*sqlx.DB, error) {
SshConfig, err := GetServerConfig(ServerName)
if err != nil {
return nil, fmt.Errorf("failed to get SSH config: %v", err)
}
MysqlConfig, err := GetMysqlConfig(MysqlName)
if err != nil {
return nil, fmt.Errorf("failed to get MySQL config: %v", err)
}
// 创建 SSH 客户端配置
sshConfig := &ssh.ClientConfig{
User: SshConfig.Username,
Auth: []ssh.AuthMethod{
ssh.Password(SshConfig.Password),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
// 连接到 SSH 服务器
sshConn, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", SshConfig.Host, SshConfig.Port), sshConfig)
if err != nil {
return nil, fmt.Errorf("failed to dial SSH: %v", err)
}
// 创建到 MySQL 服务器的隧道
mysqlConn, err := sshConn.Dial("tcp", fmt.Sprintf("%s:%d", MysqlConfig.Host, MysqlConfig.Port))
if err != nil {
return nil, fmt.Errorf("failed to dial MySQL: %v", err)
}
// 注册 MySQL 驱动
mysql.RegisterDialContext("mysql+tcp", func(ctx context.Context, addr string) (net.Conn, error) {
return mysqlConn, nil
})
// 连接到 MySQL 数据库
dsn := fmt.Sprintf("%s:%s@mysql+tcp(%s:%d)/%s", MysqlConfig.Username, MysqlConfig.Password, MysqlConfig.Host, MysqlConfig.Port, MysqlConfig.Database)
db, err := sqlx.Open("mysql", dsn)
if err != nil {
return nil, fmt.Errorf("failed to open MySQL: %v", err)
}
return db, nil
}
func connectToTopicMySQLViaSSH(ServerName, MysqlName, Topic string) (*sqlx.DB, error) {
SshConfig, err := GetServerConfig(ServerName)
if err != nil {
return nil, fmt.Errorf("failed to get SSH config: %v", err)
}
MysqlConfig, err := GetMysqlConfig(MysqlName)
if err != nil {
return nil, fmt.Errorf("failed to get MySQL config: %v", err)
}
// 创建 SSH 客户端配置
sshConfig := &ssh.ClientConfig{
User: SshConfig.Username,
Auth: []ssh.AuthMethod{
ssh.Password(SshConfig.Password),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
// 连接到 SSH 服务器
sshConn, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", SshConfig.Host, SshConfig.Port), sshConfig)
if err != nil {
return nil, fmt.Errorf("failed to dial SSH: %v", err)
}
// 创建到 MySQL 服务器的隧道
mysqlConn, err := sshConn.Dial("tcp", fmt.Sprintf("%s:%d", MysqlConfig.Host, MysqlConfig.Port))
if err != nil {
return nil, fmt.Errorf("failed to dial MySQL: %v", err)
}
// 注册 MySQL 驱动
mysql.RegisterDialContext("mysql+tcp", func(ctx context.Context, addr string) (net.Conn, error) {
return mysqlConn, nil
})
// 连接到 MySQL 数据库
dsn := fmt.Sprintf("%s:%s@mysql+tcp(%s:%d)/%s", MysqlConfig.Username, MysqlConfig.Password, MysqlConfig.Host, MysqlConfig.Port, Topic)
db, err := sqlx.Open("mysql", dsn)
if err != nil {
return nil, fmt.Errorf("failed to open MySQL: %v", err)
}
return db, nil
}
func GetMysqlDB(Server, Mysql string) *sqlx.DB {
key := fmt.Sprintf("%s_%s", Server, Mysql)
if db, ok := MysqlList[key]; ok {
return db
}
Db, err := connectToMySQLViaSSH(Server, Mysql)
if err != nil {
return nil
}
MysqlList[key] = Db
return Db
}
func GetTopicDB(Topic string) *sqlx.DB {
Server, Mysql := "log", "log"
key := fmt.Sprintf("%s_%s_topic", Server, Mysql)
if db, ok := MysqlList[key]; ok {
return db
}
Db, err := connectToTopicMySQLViaSSH(Server, Mysql, Topic)
if err != nil {
return nil
}
MysqlList[key] = Db
return Db
}
func GetAppConfig(AppId int) (*AppStruct, error) {
Db := GetMysqlDB("log", "log")
var app AppStruct
err := Db.Get(&app, "SELECT * FROM app WHERE `AppId` = ?", AppId)
if err != nil {
return nil, fmt.Errorf("failed to scan rows: %v", err)
}
return &app, nil
}

26
model/Type.go Normal file
View File

@ -0,0 +1,26 @@
package model
type AppStruct struct {
Id int `db:"id"`
AppName string `db:"AppName"`
WsHost string `db:"WsHost"`
WsPort int `db:"WsPort"`
ServerName string `db:"ServerName"`
MysqlName string `db:"MysqlName"`
Topic string `db:"Topic"`
Update int `db:"Update"`
AppId int `db:"AppId"`
}
type User struct {
Uid int `db:"dwUin"`
UserName string `db:"user_name"`
Level int `db:"level"`
Exp int `db:"exp"`
Diamond int `db:"diamond"`
Star int `db:"star"`
Energy int `db:"energy"`
LoginTime int `db:"login_time"`
LogoutTime int `db:"logout_time"`
Online string
}

90
model/User.go Normal file
View File

@ -0,0 +1,90 @@
package model
import (
"backend/msg"
util "backend/uitl"
"encoding/json"
"fmt"
"net"
"time"
"golang.org/x/net/websocket"
)
func GetUserList(AppId, PageSize, CurrentPage int) ([]*User, int, error) {
App, err := GetAppConfig(AppId)
if err != nil {
return nil, 0, err
}
db := GetMysqlDB(App.ServerName, App.MysqlName)
if db == nil {
return nil, 0, fmt.Errorf("failed to get MySQL database")
}
users := []*User{}
err = db.Select(&users, "SELECT `dwUin`, `energy`, `star`, `diamond`, `level`, `exp`, `login_time`, `logout_time`, `user_name` FROM t_player_baseinfo Order by login_time desc limit ?, ?", (CurrentPage-1)*PageSize, PageSize)
if err != nil {
return nil, 0, fmt.Errorf("failed to get user list: %v", err)
}
var total int
err = db.QueryRow("SELECT COUNT(*) FROM t_player_baseinfo").Scan(&total)
if err != nil {
return nil, 0, fmt.Errorf("failed to get user count: %v", err)
}
for _, user := range users {
if user.LogoutTime == 0 {
user.Online = "在线"
} else {
user.Online = "离线"
}
}
return users, total, nil
}
func UserDetail(Uid int) (map[string]interface{}, error) {
req := &msg.ReqAdminInfo{
Uid: int64(Uid),
}
AppId := Uid / 100000000
ServerId := Uid % 100000000 / 100000
App, err := GetAppConfig(AppId)
if err != nil {
return nil, err
}
Server, err := GetServerConfig(App.ServerName)
if err != nil {
return nil, err
}
origin := "http://localhost/"
url := fmt.Sprintf("ws://%s:%d/", Server.Host, App.WsPort+ServerId)
config, err := websocket.NewConfig(url, origin)
if err != nil {
return nil, fmt.Errorf("failed to create websocket config: %v", err)
}
config.Dialer = &net.Dialer{
Timeout: 5 * time.Second,
}
ws, err := websocket.DialConfig(config)
if err != nil {
return nil, fmt.Errorf("failed to connect to websocket: %v", err)
}
defer ws.Close()
reqBuf := util.PackMsg(req)
_, err = ws.Write(reqBuf)
if err != nil {
return nil, fmt.Errorf("failed to write to websocket: %v", err)
}
readbuf := make([]byte, 512)
n, err := ws.Read(readbuf)
if err != nil {
return nil, fmt.Errorf("failed to read from websocket: %v", err)
}
resBuf, _ := util.UnpackMsg(readbuf, n)
fmt.Println(string(resBuf))
r := make(map[string]interface{})
json.Unmarshal(resBuf, &r)
return r, nil
}

75
model/Yaml.go Normal file
View File

@ -0,0 +1,75 @@
package model
import (
"fmt"
"log"
"os"
"gopkg.in/yaml.v2"
)
type SshConfig struct {
Name string `yaml:"name"`
Host string `yaml:"host"`
Port int `yaml:"port"`
Username string `yaml:"username"`
Password string `yaml:"password"`
}
type MysqlConfig struct {
Name string `yaml:"name"`
Host string `yaml:"host"`
Port int `yaml:"port"`
Username string `yaml:"user"`
Password string `yaml:"password"`
Database string `yaml:"database"`
}
type Config struct {
Servers []SshConfig `yaml:"servers"`
Mysqls []MysqlConfig `yaml:"mysqls"`
}
var config *Config
func init() {
err := loadConfig()
if err != nil {
log.Fatalf("Failed to load config: %v", err)
}
}
func loadConfig() error {
data, err := os.ReadFile("conf/server.yml")
if err != nil {
return err
}
err = yaml.Unmarshal(data, &config)
if err != nil {
return err
}
return nil
}
func GetServerConfig(name string) (*SshConfig, error) {
for _, server := range config.Servers {
if server.Name == name {
return &server, nil
}
}
return nil, fmt.Errorf("server configuration not found: %s", name)
}
func GetMysqlConfig(name string) (*MysqlConfig, error) {
for _, mysql := range config.Mysqls {
if mysql.Name == name {
return &mysql, nil
}
}
return nil, fmt.Errorf("mysql configuration not found: %s", name)
}
func GetWsConfig(name string) (*SshConfig, error) {
return GetServerConfig("ws")
}

157
model/log.go Normal file
View File

@ -0,0 +1,157 @@
package model
import (
util "backend/uitl"
"encoding/json"
"fmt"
)
type Log struct {
Uid int `json:"Id"`
PageSize int `json:"PageSize"`
CurrentPage int `json:"CurrentPage"`
}
type ResAsset struct {
Total int `json:"total"`
Data []*ResAssetDetail `json:"data"`
}
type ResEvent struct {
Total int `json:"total"`
Data []*Event `json:"data"`
}
type ResOrder struct {
Total int `json:"total"`
Data []*Order `json:"data"`
}
type Order struct {
Id int `db:"id"`
Uid int `db:"Uid"`
OrderId string `db:"OrderId"`
Price float64 `db:"Price"`
PayChannelOrderId string `db:"PayChannelOrderId"`
ProductId int `db:"ProductId"`
CreateTime int `db:"CreateTime"`
PayTime int `db:"PayTime"`
PayType int `db:"PayType"`
Param string `db:"Param"`
Timestamp int `db:"Timestamp"`
}
type ResAssetDetail struct {
Uid int `json:"Uid"`
ChangeType string `json:"change_type"`
ChangeNum int `json:"change_num"`
ChangeAfter int `json:"change_after"`
ItemId int `json:"item_id"`
Timestamp int `json:"timestamp"`
}
type Event struct {
Id int `db:"id"`
Uid int `db:"Uid"`
Event string `db:"Event"`
Label string
Param string `db:"Param"`
Timestamp int `db:"Timestamp"`
}
func (m *Log) Asset() (*ResAsset, error) {
AppId, _ := util.ParseUid(m.Uid)
AppConfig, err := GetAppConfig(AppId)
if err != nil {
return nil, err
}
Db := GetTopicDB(AppConfig.Topic)
if Db == nil {
return nil, fmt.Errorf("failed to get mysql database")
}
assets := []*Event{}
err = Db.Select(&assets, "SELECT * FROM log_event WHERE Uid = ? and `Event` = 'asset_change' ORDER BY Timestamp DESC LIMIT ?, ?", m.Uid, (m.CurrentPage-1)*m.PageSize, m.PageSize)
if err != nil {
return nil, fmt.Errorf("failed to get asset list: %v", err)
}
var total int
err = Db.QueryRow("SELECT COUNT(*) FROM log_event WHERE Uid = ? and `Event` = 'asset_change'", m.Uid).Scan(&total)
if err != nil {
return nil, fmt.Errorf("failed to get asset count: %v", err)
}
resData := []*ResAssetDetail{}
for _, asset := range assets {
param := map[string]interface{}{}
err := json.Unmarshal([]byte(asset.Param), &param)
if err != nil {
continue
}
resData = append(resData, &ResAssetDetail{
Uid: asset.Uid,
ChangeType: param["change_type"].(string),
ChangeNum: util.Int(param["change_num"]),
ChangeAfter: util.Int(param["change_after"]),
ItemId: util.Int(param["item_id"]),
Timestamp: asset.Timestamp,
})
}
return &ResAsset{
Total: total,
Data: resData,
}, nil
}
func (m *Log) Event() (*ResEvent, error) {
AppId, _ := util.ParseUid(m.Uid)
AppConfig, err := GetAppConfig(AppId)
if err != nil {
return nil, err
}
Db := GetTopicDB(AppConfig.Topic)
if Db == nil {
return nil, fmt.Errorf("failed to get mysql database")
}
assets := []*Event{}
err = Db.Select(&assets, "SELECT * FROM log_event WHERE Uid = ? and `Event` != 'asset_change' ORDER BY Timestamp DESC LIMIT ?, ?", m.Uid, (m.CurrentPage-1)*m.PageSize, m.PageSize)
if err != nil {
return nil, fmt.Errorf("failed to get asset list: %v", err)
}
var total int
err = Db.QueryRow("SELECT COUNT(*) FROM log_event WHERE Uid = ? and `Event` != 'asset_change'", m.Uid).Scan(&total)
if err != nil {
return nil, fmt.Errorf("failed to get asset count: %v", err)
}
for _, asset := range assets {
asset.Label = asset.Event
}
return &ResEvent{
Total: total,
Data: assets,
}, nil
}
func (m *Log) Order() (*ResOrder, error) {
AppId, _ := util.ParseUid(m.Uid)
AppConfig, err := GetAppConfig(AppId)
if err != nil {
return nil, err
}
Db := GetTopicDB(AppConfig.Topic)
if Db == nil {
return nil, fmt.Errorf("failed to get mysql database")
}
assets := []*Order{}
err = Db.Select(&assets, "SELECT * FROM log_order WHERE Uid = ? ORDER BY Timestamp DESC LIMIT ?, ?", m.Uid, (m.CurrentPage-1)*m.PageSize, m.PageSize)
if err != nil {
return nil, fmt.Errorf("failed to get asset list: %v", err)
}
var total int
err = Db.QueryRow("SELECT COUNT(*) FROM log_order WHERE Uid = ? ", m.Uid).Scan(&total)
if err != nil {
return nil, fmt.Errorf("failed to get asset count: %v", err)
}
return &ResOrder{
Total: total,
Data: assets,
}, nil
}

20719
msg/Gameapi.pb.go Normal file

File diff suppressed because it is too large Load Diff

BIN
release/backend Normal file

Binary file not shown.

46
release/conf/server.yml Normal file
View File

@ -0,0 +1,46 @@
mysqls:
- host: '127.0.0.1'
name: 'merge_pet_test'
port: 3306
user: 'root'
password: 'Z4rf7eZZe500dxa'
database: 'pet_home_1'
idleTimeout: Infinity
- host: '127.0.0.1'
name: 'merge_pet_sdk'
port: 3306
user: 'root'
password: 'Z4rf7eZZe500dxa'
database: 'Merge_Pet_sdk'
idleTimeout: Infinity
- host: '127.0.0.1'
name: 'merge_pet_online'
port: 3306
user: 'root'
password: 'Xijing1!'
database: 'merge_pet_1'
idleTimeout: Infinity
- host: 'rm-f8zd2030feam53n43.mysql.rds.aliyuncs.com'
name: 'log'
port: 3306
user: 'root'
password: 'Z4rf7eZZe500dxa'
database: 'game'
idleTimeout: Infinity
servers:
- name: 'server1'
host: '1.15.182.107'
port: 22
username: 'root'
password: '`NS?VGg@7]~F3}p'
- name: 'server2'
host: '47.254.83.25'
port: 22
username: 'root'
password: 'ByWayStudios01!'
- name: 'log'
host: '8.155.14.94'
port: 22
username: 'root'
password: '-xLX]p!PQ1@SHm`A'

25
release/logs Normal file
View File

@ -0,0 +1,25 @@
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /api/user/info --> backend/controller.UserInfo (3 handlers)
[GIN-debug] POST /api/auth/login --> backend/controller.Login (3 handlers)
[GIN-debug] POST /api/user/list --> backend/controller.UserList (3 handlers)
[GIN-debug] POST /api/log/user --> backend/controller.UserDetail (3 handlers)
[GIN-debug] POST /api/log/asset --> backend/controller.Asset (3 handlers)
[GIN-debug] POST /api/log/event --> backend/controller.Event (3 handlers)
[GIN-debug] POST /api/log/order --> backend/controller.Order (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on :5320
[GIN] 2025/01/08 - 03:55:44 | 200 | 49.617µs | 172.17.0.1 | GET "/api/user/info"
[GIN] 2025/01/08 - 03:55:47 | 400 | 2.615484ms | 172.17.0.1 | POST "/api/user/list"
[GIN] 2025/01/08 - 03:57:38 | 200 | 122.755µs | 172.17.0.1 | GET "/api/user/info"
[GIN] 2025/01/08 - 03:57:39 | 200 | 827.12096ms | 172.17.0.1 | POST "/api/user/list"
[GIN] 2025/01/08 - 03:57:46 | 200 | 198.340068ms | 172.17.0.1 | POST "/api/user/list"
[GIN] 2025/01/08 - 03:57:48 | 200 | 527.361847ms | 172.17.0.1 | POST "/api/log/user"
[GIN] 2025/01/08 - 03:57:52 | 200 | 525.694211ms | 172.17.0.1 | POST "/api/log/user"
[GIN] 2025/01/08 - 03:58:09 | 200 | 497.099906ms | 172.17.0.1 | POST "/api/log/asset"
[GIN] 2025/01/08 - 03:58:13 | 200 | 154.694089ms | 172.17.0.1 | POST "/api/log/event"

2
release/pack.sh Normal file
View File

@ -0,0 +1,2 @@
cd /data/backend
GOOS=linux GOARCH=amd64 go build -o /data/backend/release/backend main.go

51
release/start.sh Normal file
View File

@ -0,0 +1,51 @@
#!/bin/sh
# Restart the backend service
# 获取命令行参数
if [ $# -ne 1 ]; then
echo "Usage: $0 [start|stop|status|restart]"
exit 1
fi
if [ $1 == "start" ]; then
echo "Starting backend..."
> log/backend.log # 清空 logs 文件
nohup ./backend >> logs 2>&1 &
echo "backend started."
elif [ $1 == "stop" ]; then
echo "Stopping backend..."
PID=$(ps -ef | grep backend | grep -v "grep" | awk '{print $2}')
if [ -z $PID ]; then
echo "backend is not running."
exit 1
fi
ps -ef | grep backend | grep -v grep | awk '{print $2}' | xargs kill
echo "backend stopped."
elif [ $1 == "status" ]; then
echo "backend status:"
PID=$(ps -ef | grep backend | grep -v "grep" | awk '{print $2}')
if [ -z $PID ]; then
echo "backend is not running."
else
echo "backend is running."
fi
elif [ $1 == "restart" ]; then
echo "Restarting backend..."
PID=$(ps -ef | grep backend | grep -v "grep" | awk '{print $2}')
if [ -n "$PID" ]; then
echo "backend stoping."
kill $PID
fi
while [ -n "$PID" ]; do
sleep 1
PID=$(ps -ef | grep backend | grep -v "grep" | awk '{print $2}')
done
echo "backend stoped."
> log/backend.log # 清空 logs 文件
nohup ./backend >> logs 2>&1 &
echo "backend restarted."
else
echo "Usage: $0 [start|stop|status|restart]"
exit 1
fi

70
uitl/util.go Normal file
View File

@ -0,0 +1,70 @@
package util
import (
"backend/msg"
"reflect"
"strconv"
"google.golang.org/protobuf/proto"
)
// 获取结构体名称
func GetStructName(v interface{}) string {
t := reflect.TypeOf(v)
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
if t.Kind() == reflect.Struct {
return t.Name()
}
return ""
}
func PackMsg(m proto.Message) []byte {
buf, _ := proto.Marshal(m)
Func := GetStructName(m)
req := &msg.AdminReq{
Func: Func,
Info: buf,
}
buf, _ = proto.Marshal(req)
return append([]byte{0, 2}, buf...)
}
func UnpackMsg(buf []byte, n int) ([]byte, error) {
res := &msg.AdminRes{}
err := proto.Unmarshal(buf[2:n], res)
if err != nil {
return nil, err
}
return res.Info, nil
}
func ParseUid(uid int) (int, int) {
AppId := uid / 100000000
ServerId := uid % 100000000 / 100000
return AppId, ServerId
}
func Int(a interface{}) int {
if a == nil {
return 0
}
switch v := a.(type) {
case int:
return v
case int32:
return int(v)
case int64:
return int(v)
case float64:
return int(v)
case string:
r, err := strconv.Atoi(v)
if err != nil {
return 0
}
return r
}
return 0
}