diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/awesomeProject.iml b/.idea/awesomeProject.iml new file mode 100644 index 0000000..5e764c4 --- /dev/null +++ b/.idea/awesomeProject.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..cc47053 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..939fef7 --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ +ROOT_DIR = $(shell pwd) +NAMESPACE = "default" +DEPLOY_NAME = "template-single" +DOCKER_NAME = "template-single" + +include ./hack/hack.mk \ No newline at end of file diff --git a/Server.go b/Server.go new file mode 100644 index 0000000..06ab7d0 --- /dev/null +++ b/Server.go @@ -0,0 +1 @@ +package main diff --git a/Utils.go b/Utils.go new file mode 100644 index 0000000..d46e9f8 --- /dev/null +++ b/Utils.go @@ -0,0 +1,17 @@ +package main + +import ( + "github.com/gogf/gf/crypto/gmd5" + "github.com/gogf/gf/util/guid" +) + +func GenerateToken(uid interface{}) (string, error) { + // 生成一个随机的 GUID 作为 token + token := guid.S() + // 使用 MD5 加密 token + encryptedToken, err := gmd5.Encrypt(token) + if err != nil { + return "", err + } + return encryptedToken, nil +} diff --git a/api/hello/hello.go b/api/hello/hello.go new file mode 100644 index 0000000..ddaf471 --- /dev/null +++ b/api/hello/hello.go @@ -0,0 +1,15 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package hello + +import ( + "context" + + "awesomeProject/api/hello/v1" +) + +type IHelloV1 interface { + Hello(ctx context.Context, req *v1.HelloReq) (res *v1.HelloRes, err error) +} diff --git a/api/hello/v1/hello.go b/api/hello/v1/hello.go new file mode 100644 index 0000000..b4dd233 --- /dev/null +++ b/api/hello/v1/hello.go @@ -0,0 +1,12 @@ +package v1 + +import ( + "github.com/gogf/gf/v2/frame/g" +) + +type HelloReq struct { + g.Meta `path:"/hello" tags:"Hello" method:"get" summary:"You first hello api"` +} +type HelloRes struct { + g.Meta `mime:"text/html" example:"string"` +} diff --git a/api/user/user.go b/api/user/user.go new file mode 100644 index 0000000..34bd1d1 --- /dev/null +++ b/api/user/user.go @@ -0,0 +1,12 @@ +package user + +import ( + "context" + + "awesomeProject/api/user/v1" +) + +type UserHandler interface { + Login(ctx context.Context, req *v1.LoginReq) (res *v1.LoginRes, err error) + Register(ctx context.Context, req *v1.RegisterReq) (res *v1.RegisterRes, err error) +} diff --git a/api/user/v1/user.go b/api/user/v1/user.go new file mode 100644 index 0000000..945ed23 --- /dev/null +++ b/api/user/v1/user.go @@ -0,0 +1,45 @@ +package v1 + +import ( + "github.com/gogf/gf/v2/frame/g" +) + +type LoginReq struct { + g.Meta `path:"/login" tags:"Login" method:"post" summary:"user login process"` + Username string `json:"username" v:"required|length:4,30#请输入用户名|用户名长度为:min到:max位"` + Password string `json:"password" v:"required|length:6,30#请输入密码|密码长度为:min到:max位"` +} +type LoginRes struct { + g.Meta `mime:"text/html" example:"{"code":200,"msg":"注册成功"}"` + Reply string `dc:"Reply content"` + Cookie string +} + +// RegisterReq 是注册接口的请求参数结构体。 +type RegisterReq struct { + g.Meta `path:"/register" tags:"Register" method:"post" summary:"处理用户注册请求"` + Username string `json:"username" v:"required|length:6,30#请输入用户名|用户名长度为:min到:max位"` + Password string `json:"password" v:"required|length:6,30#请输入密码|密码长度为:min到:max位"` + Email string `json:"email" v:"required|email#请输入有效的邮箱地址"` +} + +// RegisterRes 是注册接口的响应参数结构体。 +type RegisterRes struct { + g.Meta `mime:"application/json" example:"{"code":200,"msg":"注册成功"}"` + Code int `json:"code"` + Msg string `json:"msg"` +} + +// RegisterReq 是注册接口的请求参数结构体。 +type PushMessageReq struct { + g.Meta `path:"/api/pushmessage" tags:"PushMessage" method:"post" summary:"发送消息"` + body map[string]interface{} `json:"body"` +} + +// RegisterRes 是注册接口的响应参数结构体。 +type PushMessageRes struct { + g.Meta `mime:"application/json" example:"{"code":200,"msg":"push successed"}"` + Code int `json:"code"` + Msg map[string]interface{} `json:"msg"` +} + diff --git a/awesomeProject b/awesomeProject new file mode 100644 index 0000000..756a7e4 Binary files /dev/null and b/awesomeProject differ diff --git a/config/config.yaml b/config/config.yaml new file mode 100644 index 0000000..ab16400 --- /dev/null +++ b/config/config.yaml @@ -0,0 +1,19 @@ +database: + default: + link: "mysql:root:12345678@tcp(127.0.0.1:3306)/chanbeyEDU" + logger: + path: "/var/log/gf-app/sql" + level: "all" + stdout: "true" + +server: + + +data: + +WeChat: + classPushOfficial: + appId: "wxa4d01973e9df0619" + appSecret: "e57ed40f88fbaf10d60cad2b18a0e54e" + + \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..9f90741 --- /dev/null +++ b/go.mod @@ -0,0 +1,36 @@ +module awesomeProject + +go 1.18 + +require ( + github.com/gogf/gf v1.16.9 + github.com/gogf/gf/v2 v2.5.2 +) + + +require ( + github.com/BurntSushi/toml v1.2.0 // indirect + github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 // indirect + github.com/clbanning/mxj/v2 v2.7.0 // indirect + github.com/fatih/color v1.15.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-sql-driver/mysql v1.6.0 // indirect + github.com/gomodule/redigo v1.8.5 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/grokify/html-strip-tags-go v0.0.1 // indirect + github.com/magiconair/properties v1.8.6 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/rivo/uniseg v0.4.4 // indirect + go.opentelemetry.io/otel v1.14.0 // indirect + go.opentelemetry.io/otel/sdk v1.14.0 // indirect + go.opentelemetry.io/otel/trace v1.14.0 // indirect + golang.org/x/net v0.22.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..fa56231 --- /dev/null +++ b/go.sum @@ -0,0 +1,92 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= +github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 h1:LdXxtjzvZYhhUaonAaAKArG3pyC67kGL3YY+6hGG8G4= +github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= +github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= +github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= +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/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/gogf/gf v1.16.9 h1:Q803UmmRo59+Ws08sMVFOcd8oNpkSWL9vS33hlo/Cyk= +github.com/gogf/gf v1.16.9/go.mod h1:8Q/kw05nlVRp+4vv7XASBsMe9L1tsVKiGoeP2AHnlkk= +github.com/gogf/gf/v2 v2.5.2 h1:fACJE7DJH6iTGHGhgiNY1uuZIZtr2IqQkJ52E+wBnt8= +github.com/gogf/gf/v2 v2.5.2/go.mod h1:7yf5qp0BznfsYx7Sw49m3mQvBsHpwAjJk3Q9ZnKoUEc= +github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc= +github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0= +github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +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/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg= +go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= +go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= +go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= +go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= +go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs= +go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= +go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +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.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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= diff --git a/hack/config.yaml b/hack/config.yaml new file mode 100644 index 0000000..71bbeba --- /dev/null +++ b/hack/config.yaml @@ -0,0 +1,8 @@ + +# CLI tool, only in development environment. +# https://goframe.org/pages/viewpage.action?pageId=3673173 +gfcli: + docker: + build: "-a amd64 -s linux -p temp -ew" + tagPrefixes: + - my.image.pub/my-app \ No newline at end of file diff --git a/hack/hack-cli.mk b/hack/hack-cli.mk new file mode 100644 index 0000000..7ba0d72 --- /dev/null +++ b/hack/hack-cli.mk @@ -0,0 +1,19 @@ + +# Install/Update to the latest CLI tool. +.PHONY: cli +cli: + @set -e; \ + wget -O gf https://github.com/gogf/gf/releases/latest/download/gf_$(shell go env GOOS)_$(shell go env GOARCH) && \ + chmod +x gf && \ + ./gf install -y && \ + rm ./gf + + +# Check and install CLI tool. +.PHONY: cli.install +cli.install: + @set -e; \ + gf -v > /dev/null 2>&1 || if [[ "$?" -ne "0" ]]; then \ + echo "GoFame CLI is not installed, start proceeding auto installation..."; \ + make cli; \ + fi; \ No newline at end of file diff --git a/hack/hack.mk b/hack/hack.mk new file mode 100644 index 0000000..1a42d77 --- /dev/null +++ b/hack/hack.mk @@ -0,0 +1,75 @@ +include ./hack/hack-cli.mk + +# Update GoFrame and its CLI to latest stable version. +.PHONY: up +up: cli.install + @gf up -a + +# Build binary using configuration from hack/config.yaml. +.PHONY: build +build: cli.install + @gf build -ew + +# Parse api and generate controller/sdk. +.PHONY: ctrl +ctrl: cli.install + @gf gen ctrl + +# Generate Go files for DAO/DO/Entity. +.PHONY: dao +dao: cli.install + @gf gen dao + +# Parse current project go files and generate enums go file. +.PHONY: enums +enums: cli.install + @gf gen enums + +# Generate Go files for Service. +.PHONY: service +service: cli.install + @gf gen service + + +# Build docker image. +.PHONY: image +image: cli.install + $(eval _TAG = $(shell git describe --dirty --always --tags --abbrev=8 --match 'v*' | sed 's/-/./2' | sed 's/-/./2')) +ifneq (, $(shell git status --porcelain 2>/dev/null)) + $(eval _TAG = $(_TAG).dirty) +endif + $(eval _TAG = $(if ${TAG}, ${TAG}, $(_TAG))) + $(eval _PUSH = $(if ${PUSH}, ${PUSH}, )) + @gf docker ${_PUSH} -tn $(DOCKER_NAME):${_TAG}; + + +# Build docker image and automatically push to docker repo. +.PHONY: image.push +image.push: + @make image PUSH=-p; + + +# Deploy image and yaml to current kubectl environment. +.PHONY: deploy +deploy: + $(eval _TAG = $(if ${TAG}, ${TAG}, develop)) + + @set -e; \ + mkdir -p $(ROOT_DIR)/temp/kustomize;\ + cd $(ROOT_DIR)/manifest/deploy/kustomize/overlays/${_ENV};\ + kustomize build > $(ROOT_DIR)/temp/kustomize.yaml;\ + kubectl apply -f $(ROOT_DIR)/temp/kustomize.yaml; \ + if [ $(DEPLOY_NAME) != "" ]; then \ + kubectl patch -n $(NAMESPACE) deployment/$(DEPLOY_NAME) -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"$(shell date +%s)\"}}}}}"; \ + fi; + + +# Parsing protobuf files and generating go files. +.PHONY: pb +pb: cli.install + @gf gen pb + +# Generate protobuf files for database tables. +.PHONY: pbentity +pbentity: cli.install + @gf gen pbentity \ No newline at end of file diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go new file mode 100644 index 0000000..7033b01 --- /dev/null +++ b/internal/cmd/cmd.go @@ -0,0 +1,37 @@ +package cmd + +import ( + "context" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/os/gcmd" + + "awesomeProject/internal/controller/hello" + "awesomeProject/internal/controller/user" +) + +func MiddlewareHandler(r *ghttp.Request) { + +} + +var ( + Main = gcmd.Command{ + Name: "main", + Usage: "main", + Brief: "start http server", + Func: func(ctx context.Context, parser *gcmd.Parser) (err error) { + s := g.Server() + s.SetPort(80) + s.Group("/", func(group *ghttp.RouterGroup) { + group.Middleware(ghttp.MiddlewareHandlerResponse) + group.Bind( + hello.NewV1(), + user.NewUserController(), + ) + }) + s.Run() + return nil + }, + } +) diff --git a/internal/consts/consts.go b/internal/consts/consts.go new file mode 100644 index 0000000..d709a2b --- /dev/null +++ b/internal/consts/consts.go @@ -0,0 +1 @@ +package consts diff --git a/internal/controller/hello/hello.go b/internal/controller/hello/hello.go new file mode 100644 index 0000000..f72082f --- /dev/null +++ b/internal/controller/hello/hello.go @@ -0,0 +1,5 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package hello diff --git a/internal/controller/hello/hello_new.go b/internal/controller/hello/hello_new.go new file mode 100644 index 0000000..e34db09 --- /dev/null +++ b/internal/controller/hello/hello_new.go @@ -0,0 +1,15 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package hello + +import ( + "awesomeProject/api/hello" +) + +type ControllerV1 struct{} + +func NewV1() hello.IHelloV1 { + return &ControllerV1{} +} diff --git a/internal/controller/hello/hello_v1_hello.go b/internal/controller/hello/hello_v1_hello.go new file mode 100644 index 0000000..6d3aca5 --- /dev/null +++ b/internal/controller/hello/hello_v1_hello.go @@ -0,0 +1,13 @@ +package hello + +import ( + "context" + "github.com/gogf/gf/v2/frame/g" + + "awesomeProject/api/hello/v1" +) + +func (c *ControllerV1) Hello(ctx context.Context, req *v1.HelloReq) (res *v1.HelloRes, err error) { + g.RequestFromCtx(ctx).Response.Writeln("Hello World!") + return +} diff --git a/internal/controller/user/user.go b/internal/controller/user/user.go new file mode 100644 index 0000000..47068eb --- /dev/null +++ b/internal/controller/user/user.go @@ -0,0 +1 @@ +package user \ No newline at end of file diff --git a/internal/controller/user/user_handler.go b/internal/controller/user/user_handler.go new file mode 100644 index 0000000..4a5f439 --- /dev/null +++ b/internal/controller/user/user_handler.go @@ -0,0 +1,58 @@ +package user + +import ( + "context" + en "awesomeProject/internal/model/entity" + + "github.com/gogf/gf/crypto/gmd5" + "github.com/gogf/gf/util/guid" + "github.com/gogf/gf/v2/os/glog" + "github.com/gogf/gf/v2/os/gsession" + "github.com/gogf/gf/v2/util/gconv" + + v1 "awesomeProject/api/user/v1" +) + + +// 登录接口处理函数。 +func (c *UserController) Login(ctx context.Context, r *v1.LoginReq) (res *v1.LoginRes, err error) { + /* + record, err := g.Model("user").Where("uname=?", r.Username).Where("password=?", r.Password).One() + // 登录成功后返回响应。 + if err != nil { + glog.Error(ctx, "user not found") + return &v1.LoginRes{ + Code: 500, + Msg: "undefined username or password", + }, err + } + user := record.Map() + */ + + user, err := c.userService.Login(ctx, username, password) + if err != nil { + return &v1.LoginRes{ + Reply: "test", + Cookie: session + ";" + token, + } + } + + res = &v1.LoginRes{ + Reply: "test", + Cookie: user.Cookie, + } + + return res, nil +} + +// 注册接口处理函数。 +func (c *UserController) Register(ctx context.Context, r *v1.RegisterReq) (res *v1.RegisterRes, err error) { + // 在这里根据 req 中的用户信息进行注册逻辑处理,省略... + + // 注册成功后返回响应。 + res = &v1.RegisterRes{ + Code: 200, + Msg: "注册成功", + } + return res, nil +} diff --git a/internal/controller/user/user_new.go b/internal/controller/user/user_new.go new file mode 100644 index 0000000..3f84075 --- /dev/null +++ b/internal/controller/user/user_new.go @@ -0,0 +1,14 @@ +package user + +import ( + "awesomeProject/api/user" + "awesomeProject/internal/service" +) + +type UserController struct{ + userService *service.UserService +} + +func NewUserController() user.UserHandler { + return &UserController{} +} diff --git a/internal/dao/.gitkeep b/internal/dao/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/internal/dao/course.go b/internal/dao/course.go new file mode 100644 index 0000000..8905096 --- /dev/null +++ b/internal/dao/course.go @@ -0,0 +1,46 @@ +package dao + +import ( + "awesomeProject/internal/model/do" + "context" + + "github.com/gogf/gf/v2/database/gdb" +) + +// CourseDAO 定义了课程数据访问对象。 +type CourseDAO struct { + DB gdb.DB +} + +// NewCourseDAO 创建一个新的课程数据访问对象。 +func NewCourseDAO(db gdb.DB) *CourseDAO { + return &CourseDAO{DB: db} +} + +// CreateCourse 向数据库中插入新课程。 +func (d *CourseDAO) CreateCourse(ctx context.Context, course *do.CourseDO) error { + _, err := d.DB.Model("course").Data(course).Insert() + return err +} + +// GetCourseByID 根据课程ID从数据库中查询课程信息。 +func (d *CourseDAO) GetCourseByID(ctx context.Context, id int64) (*do.CourseDO, error) { + course := &do.CourseDO{} + err := d.DB.Model("course").Where("id", id).Scan(course) + if err != nil { + return nil, err + } + return course, nil +} + +// UpdateCourse 更新数据库中的课程信息。 +func (d *CourseDAO) UpdateCourse(ctx context.Context, course *do.CourseDO) error { + _, err := d.DB.Model("course").Data(course).Where("id", course.ID).Update() + return err +} + +// DeleteCourse 删除数据库中的课程。 +func (d *CourseDAO) DeleteCourse(ctx context.Context, id int64) error { + _, err := d.DB.Model("course").Where("id", id).Delete() + return err +} diff --git a/internal/dao/order.go b/internal/dao/order.go new file mode 100644 index 0000000..195dd92 --- /dev/null +++ b/internal/dao/order.go @@ -0,0 +1,47 @@ +package dao + +import ( + "context" + "awesomeProject/internal/model/do" + + "github.com/gogf/gf/v2/database/gdb" +) + +// OrderDAO 定义了订单数据访问对象。 +type OrderDAO struct { + DB gdb.DB + +} + +// NewOrderDAO 创建一个新的订单数据访问对象。 +func NewOrderDAO(db gdb.DB) *OrderDAO { + return &OrderDAO{DB: db} +} + +// CreateOrder 向数据库中插入新订单。 +func (d *OrderDAO) CreateOrder(ctx context.Context, order *do.OrderDO) error { + _, err := d.DB.Model("order").Data(order).Insert() + return err +} + +// GetOrderByID 根据订单ID从数据库中查询订单信息。 +func (d *OrderDAO) GetOrderByID(ctx context.Context, id int64) (*do.OrderDO, error) { + order := &do.OrderDO{} + err := d.DB.Model("order").Where("id", id).Scan(order) + if err != nil { + return nil, err + } + return order, nil +} + +// UpdateOrder 更新数据库中的订单信息。 +func (d *OrderDAO) UpdateOrder(ctx context.Context, order *do.OrderDO) error { + _, err := d.DB.Model("order").Data(order).Where("id", order.ID).Update() + return err +} + +// DeleteOrder 删除数据库中的订单。 +func (d *OrderDAO) DeleteOrder(ctx context.Context, id int64) error { + _, err := d.DB.Model("order").Where("id", id).Delete() + return err +} diff --git a/internal/dao/user.go b/internal/dao/user.go new file mode 100644 index 0000000..72ed023 --- /dev/null +++ b/internal/dao/user.go @@ -0,0 +1,72 @@ +package dao + +import ( + "context" + "github.com/gogf/gf/os/glog" + do "awesomeProject/internal/model/do" + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" + "awesomeProject/internal/model/entity" + +) + +// UserDAO 定义了用户数据访问对象。 +type UserDAO struct { + DB gdb.DB + +} + +// NewUserDAO 创建一个新的用户数据访问对象。 +func NewUserDAO() *UserDAO { + return &UserDAO{DB: g.DB()} +} + +// GetUserByID 根据用户ID从数据库中查询用户信息。 +func (d *UserDAO) GetUserByID(ctx context.Context, id int64) (*do.UserDO, error) { + user := &do.UserDO{} + err := d.DB.Model("user").Where("id", id).Scan(user) + if err != nil { + return nil, err + } + return user, nil +} + + +func newUserByUserDO(user do.UserDO) entity.User { + var userEntity entity.User + gconv.Struct(user, &userEntity) + return userEntity +} + + +// GetUserByID 根据用户ID从数据库中查询用户信息。 +func (d *UserDAO) GetUserByUsernameAndPassword(ctx context.Context, uname string,password string) (entity.User, error) { + user := &do.UserDO{} + err := d.DB.Model("user").Where("uname=? AND password=?", uname,password).Scan(user) + if err != nil { + glog.Error(ctx, "user:" + uname + " not found!") + return nil, err + } + + return newUserByUserDO(user), nil +} + +// CreateUser 向数据库中插入新用户。 +func (d *UserDAO) CreateUser(ctx context.Context, user *do.UserDO) error { + _, err := d.DB.Model("user").Data(user).Insert() + return err +} + +// UpdateUser 更新数据库中的用户信息。 +func (d *UserDAO) UpdateUser(ctx context.Context, user *do.UserDO) error { + _, err := d.DB.Model("user").Data(user).Where("id", user.UID).Update() + return err +} + +// DeleteUser 删除数据库中的用户。 +func (d *UserDAO) DeleteUser(ctx context.Context, id int64) error { + _, err := d.DB.Model("user").Where("id", id).Delete() + return err +} + + diff --git a/internal/logic/.gitkeep b/internal/logic/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/internal/model/.gitkeep b/internal/model/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/internal/model/do/.gitkeep b/internal/model/do/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/internal/model/do/course.go b/internal/model/do/course.go new file mode 100644 index 0000000..f300a90 --- /dev/null +++ b/internal/model/do/course.go @@ -0,0 +1,13 @@ +package do + +import "time" + +// CourseDO 定义了课程数据对象。 +type CourseDO struct { + ID int64 `json:"id" gconv:"id,omitempty"` + Name string `json:"name" gconv:"name,omitempty"` + Description string `json:"description" gconv:"description,omitempty"` + Price float64 `json:"price" gconv:"price,omitempty"` + CreateTime time.Time `json:"create_time" gconv:"create_time,omitempty"` + UpdateTime time.Time `json:"update_time" gconv:"update_time,omitempty"` +} diff --git a/internal/model/do/order.go b/internal/model/do/order.go new file mode 100644 index 0000000..30ea8c2 --- /dev/null +++ b/internal/model/do/order.go @@ -0,0 +1,15 @@ +package do + +import "time" + +// OrderDO 定义了订单数据对象。 +type OrderDO struct { + ID int64 `json:"id" gconv:"id,omitempty"` + UserID int64 `json:"user_id" gconv:"user_id,omitempty"` + CourseID int64 `json:"course_id" gconv:"course_id,omitempty"` + OrderNumber string `json:"order_number" gconv:"order_number,omitempty"` + Amount float64 `json:"amount" gconv:"amount,omitempty"` + Status int `json:"status" gconv:"status,omitempty"` + CreateTime time.Time `json:"create_time" gconv:"create_time,omitempty"` + UpdateTime time.Time `json:"update_time" gconv:"update_time,omitempty"` +} diff --git a/internal/model/do/user.go b/internal/model/do/user.go new file mode 100644 index 0000000..b1f6065 --- /dev/null +++ b/internal/model/do/user.go @@ -0,0 +1,26 @@ +package do + + + +// UserDO 定义了用户的数据对象结构。 +type UserDO struct { + UID int64 `json:"uid" db:"uid, primary"` + Username string `json:"uname" db:"uname"` + Password string `json:"password" db:"password"` + Email string `json:"email" db:"email"` + UserType string `json:"userType" db:"userType"` + SexOrType string `json:"sexOrType" db:"sexOrType"` + Department string `json:"department" db:"department"` + Telephone string `json:"telephone" db:"telephone"` + Role string `json:"role" db:"role"` + Cookie string `json:"cookie" db:"cookie"` +} + +type StudentDO struct{ + +} + +type UserCourseDO struct { + +} + diff --git a/internal/model/entity/.gitkeep b/internal/model/entity/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/internal/model/entity/Course.go b/internal/model/entity/Course.go new file mode 100644 index 0000000..2b7f081 --- /dev/null +++ b/internal/model/entity/Course.go @@ -0,0 +1,4 @@ +package entity + +type Course struct { +} diff --git a/internal/model/entity/Message.go b/internal/model/entity/Message.go new file mode 100644 index 0000000..7a7b5f5 --- /dev/null +++ b/internal/model/entity/Message.go @@ -0,0 +1,108 @@ +package entity + + +import ( + "context" + +) +// 定义枚举类型 +type MessageType int +type ContentType int + + + +const ( + PlatformMessage MessageType = iota + WeChatMessage + ShortNoteMessage +) + + +const ( + WeChatTemplateMessage ContentType = iota +) + + + +type Message struct { + MsgType MessageType + ContentType ContentType + Body interface{} `json:"body"` +} + +func NewWechatTemplateMessage(fields map[string]interface{}) *Message { + return &Message{ + MsgType: WeChatMessage, + ContentType: WeChatTemplateMessage, + Body: fields, + } +} + +type Msg interface{ + Do(ctx context.Context) error +} + +type MsgReq struct{ + body Message + sender User + receiver User +} + + +type PlatformMsgReq struct{ + MsgReq + +} + +func (m *MsgReq) Do(ctx context.Context) error { + // 方法实现 + return nil +} + + +func(this *PlatformMsgReq) Do(ctx context.Context) error{ + return nil +} + +type WeChatMsgReq struct{ + MsgReq + +} + +func(this *WeChatMsgReq) Do(ctx context.Context) error{ + w := NewWeChatOfficial("classPushOfficial") + err := w.PushMessage(ctx,this) + if err != nil { + return err + } + return nil +} + +func NewWeChatMsgReq(fields map[string]interface{},msgType ContentType,sender User,receiver User) *WeChatMsgReq{ + return &WeChatMsgReq{ + MsgReq{ + body: Message{ + MsgType: WeChatMessage, + ContentType: msgType, + Body: fields, + }, + sender: sender, + receiver: receiver, + }, + } +} + + + +type ShortNoteMsgReq struct{ + MsgReq + +} + +func(this *ShortNoteMsgReq) Do(ctx context.Context) error{ + return nil +} + +func NewShortNoteMsgReq(body map[string]interface{},msgType ContentType,sender User,receiver User) *ShortNoteMsgReq{ + return nil +} diff --git a/internal/model/entity/Schedule.go b/internal/model/entity/Schedule.go new file mode 100644 index 0000000..2efd4e4 --- /dev/null +++ b/internal/model/entity/Schedule.go @@ -0,0 +1,53 @@ +package entity + +import ( + "github.com/gogf/gf/os/glog" +) + +var g_runner *scheduleRunner + +// 定义一个结构体,用于携带函数和参数 +type ScheduleFunc struct { + Fn func(...interface{}) + Args []interface{} +} + +type scheduleRunner struct { + // max schedule num + maxScheduleCount int `json:"maxScheduleCount"` + reqCh chan ScheduleFunc +} + +func ReqChannel() chan ScheduleFunc { + return Runner().reqCh +} + +func (this scheduleRunner) SetMaxScheduleCount(count int) { + this.maxScheduleCount = count +} + +func (this scheduleRunner) init() { + glog.Debug("scheduleRunner init") + this.SetMaxScheduleCount(128) //default + this.reqCh = make(chan ScheduleFunc) + go func() { + glog.Debug("func is running") + for fun := range this.reqCh { + fun.Fn(fun.Args...) + } + }() +} + +func Runner() *scheduleRunner { + if g_runner == nil { + g_runner = &scheduleRunner{} + g_runner.init() + } + return g_runner +} + +func (this scheduleRunner) Run(fun ScheduleFunc) { + glog.Debug("add func to run") + this.reqCh <- fun + +} diff --git a/internal/model/entity/Statistics.go b/internal/model/entity/Statistics.go new file mode 100644 index 0000000..656fd85 --- /dev/null +++ b/internal/model/entity/Statistics.go @@ -0,0 +1,10 @@ +package entity + +type Statistics interface{ + StatisticsInfo() +} + +/* + use as proxy model ,but has some problem ,such as how to call it , whitch role could call it + +*/ \ No newline at end of file diff --git a/internal/model/entity/User.go b/internal/model/entity/User.go new file mode 100644 index 0000000..9f546ff --- /dev/null +++ b/internal/model/entity/User.go @@ -0,0 +1,265 @@ +package entity + +import ( + "context" + "github.com/gogf/gf/os/glog" + + + +) + +type Role int + +// 枚举值作为结构体字段 +const ( + R_Guest Role = iota + R_Student + R_Teacher + R_Manager + R_Customr + R_Admin +) +// +type User interface { + StatisticsInfo() + PushMessage(ctx context.Context,msg Msg) +} + + + +var g_userMgr *UserManager + +type UserObject struct { + UID int64 `json:"uid"` + Username string `json:"uname"` + Password string `json:"password"` + Email string `json:"email"` + UserType string `json:"userType"` + SexOrType string `json:"sexOrType"` + Department string `json:"department"` + Telephone string `json:"telephone"` + Cookie string `json:"cookie"` +} + + +func NewUser() UserObject{ + return UserObject{} +} + +func NewUserObject() *UserObject { + return &UserObject{} +} + + +type Student struct { + UserObject + school string `json:"school"` + classGrade string `json:"classGrade"` + studentNum string `json:"studentNum"` + courses []Course `json:"courses"` + department string `json:"department"` +} + +type Teacher struct { + UserObject + school string `json:"school"` + courses []Course `json:"courses"` + department string `json:"department"` +} + +/*manager as a part*/ +type Manager struct { + parts []User +} + +type Admin struct { + UserObject +} + +type CutomrService struct { + UserObject +} + + +func (this *Student) StatisticsInfo() { + +} + +func (this *Student) PushMessage(ctx context.Context,msg Msg) { + UserMgr().PushMessage(ctx,this,msg) +} + + + +func (this *Teacher) PushMessage(ctx context.Context,msg Msg) { + UserMgr().PushMessage(ctx,this,msg) +} + +func (this *Teacher) pushByOffcialAccounts(ctx context.Context,args ...interface{}) { + if len(args) != 1 { + glog.Debug("Error: Expected exactly one argument") + return + } + msg, ok := args[0].(Msg) + if !ok { + glog.Error("Error: Expected Message type argument") + } + + w := NewWeChatOfficial("default") + err := w.PushMessage(ctx,msg) + if err != nil { + return + } + + /* + + */ + +} + +/*@func +*push message to short note + */ +func (this *Teacher) pushByShortNote(args ...interface{}) { + +} + +func (this *Teacher) pushByPlatform(args ...interface{}) { + +} + +func (this *Teacher) courseStatistics(course *Course) { + +} + +func (this *Teacher) StatisticsInfo() { + +} + +func (this *Teacher) pushEveryOneByOfficial(){ + +} + + + +func (this *Manager) PushByOfficialAccounts() { + +} + +func (this *Manager) PushByShortNote() { + +} + +func (this *Manager) AddCourse() { + +} + +func (this *Manager) DepartmentStatistics() { + +} + +func (this *Manager) StatisticsInfo() { + +} + +func (this *Manager) PushMessage(ctx context.Context,msg Msg) { + UserMgr().PushMessage(ctx ,this,msg) +} + + + +func (this *Admin) SalesStatics() { + +} + +func (this *Admin) CreateAccount() (UserObject, error) { + return UserObject{}, nil +} + +func (this *Admin) GetAccount() { + +} + +func (this *Admin) ChangeAccount() { + +} + +func (this *Admin) DeleteAccount() { + +} + +func (this *Admin) GetAccountsByBelongOf() { + +} + +func (this *Admin) GetAccountsByCourse() { + +} + +func (this *Admin) StatisticsInfo() { + +} + +func (this *Admin) PushMessage(ctx context.Context,msg Msg) { + UserMgr().PushMessage(ctx,this,msg) +} + + +func (this *CutomrService) StatisticsInfo(){ + +} + +func (this *CutomrService) SalesStatics() { + +} + +func (this *CutomrService) PushMessage(ctx context.Context,msg Msg) { + UserMgr().PushMessage(ctx,this,msg) +} + +func (this *CutomrService) OrderQuery() { + +} + +type UserManager struct { + userRequestQueue *scheduleRunner + +} + +func (this *UserManager) PushMessage(ctx context.Context,user User,req Msg) { + glog.Debug("push message") + req.Do(ctx) +} + +func (this *UserManager) QueryAccountsByDepartment(dept string) { + +} + +func (this *UserManager) QueryAccountsById(id string) { + +} + +/* +delete +*/ +func Run(fun func(...interface{}), args ...interface{}) { + sf := ScheduleFunc{ + Fn: fun, + Args: args, + } + UserMgr().userRequestQueue.Run(sf) +} + +/* +delete +*/ +func UserMgr() *UserManager { + if g_userMgr == nil { + g_userMgr = &UserManager{ + userRequestQueue: Runner(), + } + } + return g_userMgr +} + + diff --git a/internal/model/entity/WeChatOfficialAccount.go b/internal/model/entity/WeChatOfficialAccount.go new file mode 100644 index 0000000..5702298 --- /dev/null +++ b/internal/model/entity/WeChatOfficialAccount.go @@ -0,0 +1,264 @@ +package entity + +import ( + "context" + "encoding/json" + "io" + "net/http" + "time" + + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/os/glog" + "github.com/gogf/gf/os/gtime" +) + +type WeChatOfficial struct { + name string + url string `json:"url"` + accessToken string `json:"access_Token"` + expiresIn int64 `json:"expires_In"` + appId string + appSecret string + client *ghttp.Client +} + +func NewWeChatOfficial(name string) *WeChatOfficial { + we := WeChatOfficial{ + url: "https://api.weixin.qq.com", + name: name, + } + + err := we.UpdateAccessToken() + we.client = g.Client() + if err != nil { + glog.Debug("get access token error") + } + return &we +} + +func (this *WeChatOfficial) UpdateAccessToken() error { + // 构造请求 URL + config := g.Cfg() + url := this.url + "/cgi-bin/token?grant_type=client_credential&appid=" + config.GetString("WeChat.pushOfficial.appId") + "&secret=" + config.GetString("WeChat.pushOfficial.appSecret") + glog.Debug(config.GetString("WeChat.pushOfficial.appId")) + glog.Debug(url) + // 创建 HTTP 客户端 + client := http.Client{ + Timeout: 10 * time.Second, // 设置超时时间为 10 秒 + } + + // 发送 GET 请求 + resp, err := client.Get(url) + if err != nil { + return err + } + + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + glog.Debug(err.Error()) + } + }(resp.Body) + + // 解析响应的 JSON 数据 + var result struct { + AccessToken string `json:"access_token"` + ExpiresIn int64 `json:"expires_in"` + } + if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { + return err + } + + // 更新 AccessToken 和 ExpiresIn 字段 + this.accessToken = result.AccessToken + glog.Debug(this.accessToken) + this.expiresIn = time.Now().Unix() + result.ExpiresIn // 计算过期时间 + return nil +} + +func (this *WeChatOfficial) PushMessage(ctx context.Context,msg Msg) error { + currentTime := gtime.Now() + timestamp := currentTime.Timestamp() + if timestamp > this.expiresIn { + err := this.UpdateAccessToken() + if err != nil { + glog.Error("update token failed") + return err + } + } + // 判断接口类型是否为子类 + if cmsg, ok := msg.(*WeChatMsgReq); ok { + glog.Debug(cmsg.body.Body) + switch cmsg.body.ContentType { + case WeChatTemplateMessage: + err := this.pushTemplateMsg(cmsg.body) + if err != nil { + return err + } + break + } + //fmt.Printf("Name: %s, Width: %.2f, Height: %.2f\n", child.Name, child.Width, child.Height) + } else { + glog.Error("unexceptd param msg not is type WeChatMsgReq") + } + + return nil +} + +/* +* @brief 设置所属行业 +* @details 每月只能修改一次,可在公众号后台修改 + */ +func (this *WeChatOfficial) setIndustry(msg Message) error { + // 构造请求 URL + url := this.url + "/cgi-bin/template/api_set_industry?access_token=" + this.accessToken + + body, err := json.Marshal(msg) + if err != nil { + glog.Debug("JSON marshal error:", err) + } + + // 发送 GET 请求 + resp, err := this.client.Post(url, body) + if err != nil { + return err + } + + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + glog.Debug(err.Error()) + } + }(resp.Body) + + // 解析响应数据 + result := resp.ReadAllString() + glog.Debug("Response:", result) + + return nil + +} + +/* +* @brief 获取设置的行业信息 + */ +func (this *WeChatOfficial) getIndustry() error { + // 构造请求 URL + url := this.url + "/cgi-bin/template/get_industry?access_token=" + this.accessToken + + // 发送 POST 请求 + response, err := this.client.Get(url) + if err != nil {// + //2 获取设置的行业信息 + // + //3 获得模板ID + // + //4 获取模板列表 + // + //5 删除模板 + // + //6 发送模板消息 + // + //7 事件推送 + glog.Debug(err) + return err + } + defer response.Close() + + // 解析响应数据 + result := response.ReadAllString() + glog.Debug("Response:", result) + + return nil +} + +/* +* @brief 获得模板ID + */ +func (this *WeChatOfficial) getTemplateId(msg Message) error { + // 构造请求 URL + url := this.url + "/cgi-bin/template/api_add_template?access_token=" + this.accessToken + + body, err := json.Marshal(msg) + if err != nil { + glog.Debug("JSON marshal error:", err) + } + // 发送 POST 请求 + response, err := this.client.Post(url, body) + if err != nil { + glog.Debug(err) + return err + } + defer response.Close() + + // 解析响应数据 + result := response.ReadAllString() + glog.Debug("Response:", result) + + return nil +} + +/* +* @brief 删除模板 +* @param msg.body : template_id + */ +func (this *WeChatOfficial) deleteTemplate(msg Message) error { + // 构造请求 URL + url := this.url + "/cgi-bin/template/del_private_template?access_token=" + this.accessToken + // 发送 POST 请求 + body, err := json.Marshal(msg) + if err != nil { + glog.Debug("JSON marshal error:", err) + } + response, err := this.client.Post(url, body) + if err != nil { + glog.Debug(err) + return err + } + defer response.Close() + + // 解析响应数据 + result := response.ReadAllString() + glog.Debug("Response:", result) + + return nil +} + +/* + - @brief 删除模板 + - @param msg.body : + { + "touser":接收者openid + "template_id":模板ID + "url":模板跳转链接(海外账号没有跳转能力) + "miniprogram":跳小程序所需数据,不需跳小程序可不用传该数据 + "appid":所需跳转到的小程序appid(该小程序appid必须与发模板消息的公众号是绑定关联关系,暂不支持小游戏) + "pagepath":所需跳转到小程序的具体页面路径,支持带参数,(示例index?foo=bar),要求该小程序已发布,暂不支持小游戏 + "client_msg_id":防重入id。对于同一个openid + client_msg_id, 只发送一条消息,10分钟有效,超过10分钟不保证效果。若无防重入需求,可不填 + "data":模板数据 + } + } +*/ +func (this *WeChatOfficial) pushTemplateMsg(msg Message) error { + // 构造请求 URL + url := this.url + "/cgi-bin/template/send?access_token=" + this.accessToken + // 发送 POST 请求 + body, err := json.Marshal(msg) + glog.Debug("POST", url) + if err != nil { + glog.Debug("JSON marshal error:", err) + } + response, err := this.client.Post(url, body) + if err != nil { + glog.Debug(err) + return err + } + defer response.Close() + + // 解析响应数据 + result := response.ReadAllString() + glog.Debug("Response:", result) + + return nil +} diff --git a/internal/packed/packed.go b/internal/packed/packed.go new file mode 100644 index 0000000..e20ab1e --- /dev/null +++ b/internal/packed/packed.go @@ -0,0 +1 @@ +package packed diff --git a/internal/service/.gitkeep b/internal/service/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/internal/service/user.go b/internal/service/user.go new file mode 100644 index 0000000..bd0278f --- /dev/null +++ b/internal/service/user.go @@ -0,0 +1,115 @@ +package service + +import ( + "context" + "awesomeProject/internal/dao" + "awesomeProject/internal/model/entity" + "github.com/gogf/gf/crypto/gmd5" + "github.com/gogf/gf/util/guid" + "github.com/gogf/gf/v2/os/gsession" + "github.com/gogf/gf/v2/util/gconv" + "github.com/gogf/gf/v2/os/glog" +) + +type UserService struct { + userDAO *dao.UserDAO +} + +func NewUserService() *UserService { + return &UserService{} +} +func GenerateToken(data interface{}) (string, error) { + // 生成一个随机的 GUID 作为 token + token := guid.S(gconv.Bytes(data)) + // 使用 MD5 加密 token + encryptedToken, err := gmd5.Encrypt(token) + if err != nil { + return "", err + } + return encryptedToken, nil +} + + +func (s *UserService) Login(ctx context.Context, username string, password string) (*entity.User, error) { + // 调用 Dao 层的方法查询用户信息 + user, err := s.userDAO.GetUserByUsernameAndPassword(ctx, username, password) + if err != nil { + return nil, err + } + // 生成 token + token, _ := GenerateToken(password) + token = "token=" + token + session := gsession.NewSessionId() + glog.Info(ctx, token) + user.Cookie = token + ";" + session; + return user, nil +} + +// RegisterUser 注册用户 +func (s *UserService) RegisterUser(ctx context.Context, user *entity.User) error { + // 执行注册逻辑,例如验证用户信息、生成密码哈希等 + + // 调用 DAO 层保存用户信息到数据库 + err := userDao.SaveUser(ctx, user) + if err != nil { + return err + } + + return nil +} + +// GetUserByID 根据用户ID获取用户信息 +func (s *UserService) GetUserByID(ctx context.Context, userID int64) (*entity.User, error) { + // 调用 DAO 层获取用户信息 + user, err := userDao.GetUserByID(ctx, userID) + if err != nil { + return nil, err + } + + return user, nil +} + + +func (s *UserService) PushMessage(ctx context.Context, req Msg){ + glog.Debug("push message") + go func(){ + err := req.Do(ctx) + if err != nil{ + glog.Error(ctx,"push message error:" ,err) + } + }() + +} + +func (s *UserService) StatisticsInfo(ctx context.Context,user entity.User){ + glog.Debug("Statistics Info") + go func(){ + err := user.StatisticsInfo(ctx) + if err != nil{ + glog.Error(ctx,"Statistics Info error:" ,err) + } + }() + +} + + + +type StudentServer struct { + +} + +type TeacherServer struct { + +} + +type ManagerServer struct { + +} + +type AdminServer struct { + +} + +type CutomrServiceServer struct { + +} diff --git a/main b/main new file mode 100644 index 0000000..9a59d73 Binary files /dev/null and b/main differ diff --git a/main.go b/main.go new file mode 100644 index 0000000..c0a2a8f --- /dev/null +++ b/main.go @@ -0,0 +1,31 @@ +package main + +import ( + "fmt" + "awesomeProject/internal/cmd" + _ "awesomeProject/internal/packed" + + "github.com/gogf/gf/v2/os/gctx" + "github.com/gogf/gf/frame/g" +) + + + + + +func init() { + + users, err := g.DB().Model("user").All() + if err != nil { + // 处理错误 + fmt.Println(err.Error()) + } else { + // 处理查询结果 + fmt.Println(users) + } + +} + +func main() { + cmd.Main.Run(gctx.GetInitCtx()) +} diff --git a/manifest/config/config.yaml b/manifest/config/config.yaml new file mode 100644 index 0000000..ad86d5c --- /dev/null +++ b/manifest/config/config.yaml @@ -0,0 +1,11 @@ +server: + address: ":8000" + openapiPath: "/api.json" + swaggerPath: "/swagger" + +logger: + level : "all" + stdout: true + + + diff --git a/manifest/deploy/kustomize/base/deployment.yaml b/manifest/deploy/kustomize/base/deployment.yaml new file mode 100644 index 0000000..28f1d69 --- /dev/null +++ b/manifest/deploy/kustomize/base/deployment.yaml @@ -0,0 +1,21 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: template-single + labels: + app: template-single +spec: + replicas: 1 + selector: + matchLabels: + app: template-single + template: + metadata: + labels: + app: template-single + spec: + containers: + - name : main + image: template-single + imagePullPolicy: Always + diff --git a/manifest/deploy/kustomize/base/kustomization.yaml b/manifest/deploy/kustomize/base/kustomization.yaml new file mode 100644 index 0000000..302d92d --- /dev/null +++ b/manifest/deploy/kustomize/base/kustomization.yaml @@ -0,0 +1,8 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- deployment.yaml +- service.yaml + + + diff --git a/manifest/deploy/kustomize/base/service.yaml b/manifest/deploy/kustomize/base/service.yaml new file mode 100644 index 0000000..608771c --- /dev/null +++ b/manifest/deploy/kustomize/base/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: template-single +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 8000 + selector: + app: template-single + diff --git a/manifest/deploy/kustomize/overlays/develop/configmap.yaml b/manifest/deploy/kustomize/overlays/develop/configmap.yaml new file mode 100644 index 0000000..3b1d0af --- /dev/null +++ b/manifest/deploy/kustomize/overlays/develop/configmap.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: template-single-configmap +data: + config.yaml: | + server: + address: ":8000" + openapiPath: "/api.json" + swaggerPath: "/swagger" + + logger: + level : "all" + stdout: true diff --git a/manifest/deploy/kustomize/overlays/develop/deployment.yaml b/manifest/deploy/kustomize/overlays/develop/deployment.yaml new file mode 100644 index 0000000..04e4851 --- /dev/null +++ b/manifest/deploy/kustomize/overlays/develop/deployment.yaml @@ -0,0 +1,10 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: template-single +spec: + template: + spec: + containers: + - name : main + image: template-single:develop \ No newline at end of file diff --git a/manifest/deploy/kustomize/overlays/develop/kustomization.yaml b/manifest/deploy/kustomize/overlays/develop/kustomization.yaml new file mode 100644 index 0000000..4731c47 --- /dev/null +++ b/manifest/deploy/kustomize/overlays/develop/kustomization.yaml @@ -0,0 +1,14 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- ../../base +- configmap.yaml + +patchesStrategicMerge: +- deployment.yaml + +namespace: default + + + diff --git a/manifest/docker/Dockerfile b/manifest/docker/Dockerfile new file mode 100644 index 0000000..d3abe8f --- /dev/null +++ b/manifest/docker/Dockerfile @@ -0,0 +1,16 @@ +FROM loads/alpine:3.8 + +############################################################################### +# INSTALLATION +############################################################################### + +ENV WORKDIR /app +ADD resource $WORKDIR/ +ADD ./temp/linux_amd64/main $WORKDIR/main +RUN chmod +x $WORKDIR/main + +############################################################################### +# START +############################################################################### +WORKDIR $WORKDIR +CMD ./main diff --git a/manifest/docker/docker.sh b/manifest/docker/docker.sh new file mode 100644 index 0000000..ff393f9 --- /dev/null +++ b/manifest/docker/docker.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# This shell is executed before docker build. + + + + + diff --git a/manifest/i18n/.gitkeep b/manifest/i18n/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/manifest/protobuf/.keep-if-necessary b/manifest/protobuf/.keep-if-necessary new file mode 100644 index 0000000..e69de29 diff --git a/resource/public/html/.gitkeep b/resource/public/html/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resource/public/plugin/.gitkeep b/resource/public/plugin/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resource/public/resource/css/.gitkeep b/resource/public/resource/css/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resource/public/resource/css/style.css b/resource/public/resource/css/style.css new file mode 100644 index 0000000..9516cd4 --- /dev/null +++ b/resource/public/resource/css/style.css @@ -0,0 +1,40 @@ +/* Navigation 样式 */ +.navbar { + background-color: #007bff; + padding: 10px 0; /* 添加上下内边距 */ + overflow: hidden; /* 触发 BFC(块级格式化上下文)以防止浮动元素影响布局 */ +} + +.navbar ul { + list-style-type: none; /* 移除列表默认样式 */ + margin: 0; + padding: 0; + overflow: hidden; /* 清除浮动 */ +} + +.navbar li { + float: left; /* 将列表项水平排列 */ +} + +.navbar li a { + display: block; /* 将链接显示为块级元素,使其充满父元素的宽度 */ + color: #fff; + text-align: center; + padding: 14px 16px; /* 添加上下内边距,左右内边距 */ + text-decoration: none; +} + +.navbar li a:hover { + background-color: #0056b3; /* 鼠标悬停时的背景颜色 */ +} + +/* Footer 样式 */ +.footer { + background-color: #ddd; /* 设置背景颜色为灰色 */ + color: #333; /* 设置文字颜色 */ + padding: 20px; + text-align: center; + position: fixed; /* 将 footer 固定在底部 */ + width: 100%; /* 设置宽度为100% */ + bottom: 0; /* 将 footer 置底 */ +} diff --git a/resource/public/resource/image/.gitkeep b/resource/public/resource/image/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resource/public/resource/js/.gitkeep b/resource/public/resource/js/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resource/template/.gitkeep b/resource/template/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/template/config b/template/config new file mode 100644 index 0000000..e69de29 diff --git a/template/container.html b/template/container.html new file mode 100644 index 0000000..2243d03 --- /dev/null +++ b/template/container.html @@ -0,0 +1,16 @@ +
+
+
+

Column 1

+

This is the content of column 1.

+
+
+

Column 2

+

This is the content of column 2.

+
+
+

Column 3

+

This is the content of column 3.

+
+
+
diff --git a/template/footer.html b/template/footer.html new file mode 100644 index 0000000..afa628b --- /dev/null +++ b/template/footer.html @@ -0,0 +1,7 @@ + + diff --git a/template/html5.html b/template/html5.html new file mode 100644 index 0000000..63ef56f --- /dev/null +++ b/template/html5.html @@ -0,0 +1,19 @@ + + + + + + Layout Example + + + +{{ include "nav.html" .}} + + +{{ include .mainTpl .}} + + +{{ include "footer.html" .}} + + + diff --git a/template/layout.html b/template/layout.html new file mode 100644 index 0000000..8e89aff --- /dev/null +++ b/template/layout.html @@ -0,0 +1,66 @@ + + + + + + Layout Example + + + + + +{{ include "nav.html" .}} + + +{{ include .mainTpl .}} + + +{{ include "footer.html" .}} + + + + + + diff --git a/template/nav.html b/template/nav.html new file mode 100644 index 0000000..99265af --- /dev/null +++ b/template/nav.html @@ -0,0 +1,15 @@ + + \ No newline at end of file diff --git a/utility/.gitkeep b/utility/.gitkeep new file mode 100644 index 0000000..e69de29