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