初步框架代码
This commit is contained in:
18
server/app/internal/handlers/action_routes_gen.go
Normal file
18
server/app/internal/handlers/action_routes_gen.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/iapologizewhenimwrong/Vestmore_GO/server/app/internal/handlers/actions"
|
||||
)
|
||||
|
||||
var HandlersFuncRoutes map[string]gin.HandlerFunc = make(map[string]gin.HandlerFunc)
|
||||
|
||||
func init() {
|
||||
HandlersFuncRoutes["account/forgetSmsCode"] = actions.AccountForgetSmsCode
|
||||
HandlersFuncRoutes["account/loginWithEmailPassword"] = actions.AccountLoginWithEmailPassword
|
||||
HandlersFuncRoutes["account/loginWithTelephonePassword"] = actions.AccountLoginWithTelephonePassword
|
||||
HandlersFuncRoutes["account/registerEmailCode"] = actions.AccountRegisterEmailCode
|
||||
HandlersFuncRoutes["account/registerSmsCode"] = actions.AccountRegisterSmsCode
|
||||
HandlersFuncRoutes["base/getToken"] = actions.BaseGetToken
|
||||
HandlersFuncRoutes["member/alterPassword"] = actions.MemberAlterPassword
|
||||
}
|
||||
92
server/app/internal/handlers/actions/auth.go
Normal file
92
server/app/internal/handlers/actions/auth.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package actions
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Action base/getToken
|
||||
// Base_GetToken
|
||||
// action: string;
|
||||
// app_market: string;
|
||||
// lang: string;
|
||||
// token: string;
|
||||
func BaseGetToken(ctx *gin.Context) {
|
||||
param := &BaseGetTokenParam{}
|
||||
ctx.ShouldBind(param)
|
||||
log.Println()
|
||||
}
|
||||
|
||||
// @Action account/loginWithTelephonePassword
|
||||
// AccountLoginWithTelephonePassword
|
||||
// action: string;
|
||||
// country_code: string;
|
||||
// device?: string;
|
||||
// lang: string;
|
||||
// password: string;
|
||||
// telephone: string;
|
||||
// token?: string;
|
||||
// version?: string;
|
||||
func AccountLoginWithTelephonePassword(ctx *gin.Context) {
|
||||
// ctx.ShouldBind()
|
||||
log.Println()
|
||||
}
|
||||
|
||||
// @Action account/registerSmsCode
|
||||
// AccountRegisterSmsCode
|
||||
// action: string;
|
||||
// country_code?: string;
|
||||
// telephone?: string;
|
||||
// token: string;
|
||||
func AccountRegisterSmsCode(ctx *gin.Context) {
|
||||
// ctx.ShouldBind()
|
||||
log.Println()
|
||||
}
|
||||
|
||||
// @Action account/forgetSmsCode
|
||||
// AccountForgetSmsCode
|
||||
// action: string;
|
||||
// country_code?: string;
|
||||
// telephone?: string;
|
||||
// token: string;
|
||||
func AccountForgetSmsCode(ctx *gin.Context) {
|
||||
// ctx.ShouldBind()
|
||||
log.Println()
|
||||
}
|
||||
|
||||
// @Action account/registerEmailCode
|
||||
// AccountRegisterEmailCode
|
||||
// action: string;
|
||||
// email?: string;
|
||||
// token: string;
|
||||
func AccountRegisterEmailCode(ctx *gin.Context) {
|
||||
// ctx.ShouldBind()
|
||||
log.Println()
|
||||
}
|
||||
|
||||
// @Action member/alterPassword
|
||||
// MemberAlterPassword
|
||||
// action: string;
|
||||
// confirm_password: string;
|
||||
// new_password: string;
|
||||
// old_password: string;
|
||||
// token?: string;
|
||||
func MemberAlterPassword(ctx *gin.Context) {
|
||||
// ctx.ShouldBind()
|
||||
log.Println()
|
||||
}
|
||||
|
||||
// @Action account/loginWithEmailPassword
|
||||
// AccountLoginWithEmailPassword
|
||||
// action: string;
|
||||
// device?: string;
|
||||
// email: string;
|
||||
// lang: string;
|
||||
// password: string;
|
||||
// token?: string;
|
||||
// version?: string;
|
||||
func AccountLoginWithEmailPassword(ctx *gin.Context) {
|
||||
// ctx.ShouldBind()
|
||||
log.Println()
|
||||
}
|
||||
57
server/app/internal/handlers/actions/types_gen.go
Normal file
57
server/app/internal/handlers/actions/types_gen.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package actions
|
||||
|
||||
type AccountForgetSmsCodeParam struct {
|
||||
Action string `json:"action" form:"action" binding:"-"`
|
||||
CountryCode string `json:"country_code" form:"country_code" binding:"required"`
|
||||
Telephone string `json:"telephone" form:"telephone" binding:"required"`
|
||||
Token string `json:"token" form:"token" binding:"-"`
|
||||
}
|
||||
|
||||
type AccountLoginWithEmailPasswordParam struct {
|
||||
Action string `json:"action" form:"action" binding:"-"`
|
||||
Device string `json:"device" form:"device" binding:"required"`
|
||||
Email string `json:"email" form:"email" binding:"-"`
|
||||
Lang string `json:"lang" form:"lang" binding:"-"`
|
||||
Password string `json:"password" form:"password" binding:"-"`
|
||||
Token string `json:"token" form:"token" binding:"required"`
|
||||
Version string `json:"version" form:"version" binding:"required"`
|
||||
}
|
||||
|
||||
type AccountLoginWithTelephonePasswordParam struct {
|
||||
Action string `json:"action" form:"action" binding:"-"`
|
||||
CountryCode string `json:"country_code" form:"country_code" binding:"-"`
|
||||
Device string `json:"device" form:"device" binding:"required"`
|
||||
Lang string `json:"lang" form:"lang" binding:"-"`
|
||||
Password string `json:"password" form:"password" binding:"-"`
|
||||
Telephone string `json:"telephone" form:"telephone" binding:"-"`
|
||||
Token string `json:"token" form:"token" binding:"required"`
|
||||
Version string `json:"version" form:"version" binding:"required"`
|
||||
}
|
||||
|
||||
type AccountRegisterEmailCodeParam struct {
|
||||
Action string `json:"action" form:"action" binding:"-"`
|
||||
Email string `json:"email" form:"email" binding:"required"`
|
||||
Token string `json:"token" form:"token" binding:"-"`
|
||||
}
|
||||
|
||||
type AccountRegisterSmsCodeParam struct {
|
||||
Action string `json:"action" form:"action" binding:"-"`
|
||||
CountryCode string `json:"country_code" form:"country_code" binding:"required"`
|
||||
Telephone string `json:"telephone" form:"telephone" binding:"required"`
|
||||
Token string `json:"token" form:"token" binding:"-"`
|
||||
}
|
||||
|
||||
type BaseGetTokenParam struct {
|
||||
Action string `json:"action" form:"action" binding:"-"`
|
||||
AppMarket string `json:"app_market" form:"app_market" binding:"-"`
|
||||
Lang string `json:"lang" form:"lang" binding:"-"`
|
||||
Token string `json:"token" form:"token" binding:"-"`
|
||||
}
|
||||
|
||||
type MemberAlterPasswordParam struct {
|
||||
Action string `json:"action" form:"action" binding:"-"`
|
||||
ConfirmPassword string `json:"confirm_password" form:"confirm_password" binding:"-"`
|
||||
NewPassword string `json:"new_password" form:"new_password" binding:"-"`
|
||||
OldPassword string `json:"old_password" form:"old_password" binding:"-"`
|
||||
Token string `json:"token" form:"token" binding:"required"`
|
||||
}
|
||||
14
server/app/internal/handlers/gen_action_routes.tpl
Normal file
14
server/app/internal/handlers/gen_action_routes.tpl
Normal file
@@ -0,0 +1,14 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/iapologizewhenimwrong/Vestmore_GO/server/app/internal/handlers/actions"
|
||||
)
|
||||
|
||||
var HandlersFuncRoutes map[string]gin.HandlerFunc = make(map[string]gin.HandlerFunc)
|
||||
|
||||
func init() {
|
||||
{{- range .}}
|
||||
HandlersFuncRoutes["{{.ActionName}}"] = actions.{{.FuncName}}
|
||||
{{- end}}
|
||||
}
|
||||
193
server/app/internal/handlers/gen_action_routes_test.go
Normal file
193
server/app/internal/handlers/gen_action_routes_test.go
Normal file
@@ -0,0 +1,193 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/format"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"text/template"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
func TestGenActionsHandlerFunc(t *testing.T) {
|
||||
createActionRoutesGen()
|
||||
}
|
||||
|
||||
// 生成路由代码
|
||||
func createActionRoutesGen() {
|
||||
var err error
|
||||
af := getActionsInfo()
|
||||
tpl, err := template.ParseGlob("./*.tpl")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
genFile(tpl, "gen_action_routes.tpl", "./action_routes_gen.go", af)
|
||||
genFile(tpl, "types_gen.tpl", "./actions/types_gen.go", af)
|
||||
}
|
||||
|
||||
func genFile(tpl *template.Template, executeTemplate string, genFilePath string, tplParam any) {
|
||||
|
||||
var buf bytes.Buffer
|
||||
err := tpl.ExecuteTemplate(&buf, executeTemplate, tplParam)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
data, err := format.Source(buf.Bytes())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
log.Println(string(data))
|
||||
|
||||
f, err := os.OpenFile(genFilePath, os.O_TRUNC|os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
f.Write(data)
|
||||
f.Close()
|
||||
}
|
||||
|
||||
type actionsFunc struct {
|
||||
ActionName string
|
||||
FuncName string
|
||||
ParamStruct *paramStruct
|
||||
}
|
||||
|
||||
type paramStructField struct {
|
||||
ParamName string
|
||||
ParamNameCamel string
|
||||
ParamType string
|
||||
ParamBinding string
|
||||
}
|
||||
|
||||
type paramStruct struct {
|
||||
ParamStructName string
|
||||
ParamFields []paramStructField
|
||||
}
|
||||
|
||||
func getActionsInfo() map[string]*actionsFunc {
|
||||
regActionRe := regexp.MustCompile(`(?i)action +([^ ]+)`)
|
||||
paramStructRe := regexp.MustCompile(` +([a-zA-Z_\-/]+)(\?{0,1}): +(\w+) ?;`)
|
||||
|
||||
dir := "actions"
|
||||
actionsMap := make(map[string]*actionsFunc)
|
||||
|
||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.IsDir() && strings.HasSuffix(info.Name(), ".go") {
|
||||
fset := token.NewFileSet()
|
||||
|
||||
file, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, decl := range file.Decls {
|
||||
fn, ok := decl.(*ast.FuncDecl)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if fn.Doc != nil {
|
||||
var pstru *paramStruct
|
||||
var af *actionsFunc
|
||||
for _, comment := range fn.Doc.List {
|
||||
// 匹配 @Action 提取
|
||||
if strings.Contains(comment.Text, "@Action") || strings.Contains(comment.Text, "@action") {
|
||||
matches := regActionRe.FindStringSubmatch(comment.Text)
|
||||
if len(matches) != 0 {
|
||||
af = &actionsFunc{
|
||||
ActionName: matches[1],
|
||||
FuncName: fn.Name.Name,
|
||||
}
|
||||
actionsMap[af.ActionName] = af
|
||||
} else {
|
||||
log.Panicf("action 无法匹配: %s", comment.Text)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
psvalue := paramStructRe.FindAllStringSubmatch(comment.Text, -1)
|
||||
if len(psvalue) != 0 {
|
||||
|
||||
if pstru == nil {
|
||||
pstru = ¶mStruct{
|
||||
ParamStructName: fn.Name.Name + "Param",
|
||||
}
|
||||
af.ParamStruct = pstru
|
||||
}
|
||||
|
||||
pf := paramStructField{}
|
||||
|
||||
paramInfo := psvalue[0]
|
||||
|
||||
pf.ParamName = paramInfo[1]
|
||||
pf.ParamNameCamel = toCamelCase(pf.ParamName)
|
||||
|
||||
paramRequired := paramInfo[2]
|
||||
if paramRequired != "" {
|
||||
pf.ParamBinding = "required"
|
||||
} else {
|
||||
pf.ParamBinding = "-"
|
||||
}
|
||||
|
||||
pf.ParamType = paramInfo[3]
|
||||
|
||||
pstru.ParamFields = append(pstru.ParamFields, pf)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
panic(fmt.Sprint("Error:", err))
|
||||
// return actionsMap
|
||||
}
|
||||
|
||||
for action, funcNames := range actionsMap {
|
||||
fmt.Printf("Action: %s %v\n", action, funcNames)
|
||||
}
|
||||
|
||||
return actionsMap
|
||||
}
|
||||
|
||||
func TestCase2(t *testing.T) {
|
||||
eg := `// device: string;`
|
||||
re := regexp.MustCompile(` +([a-zA-Z_\-/]+)(\?{0,1}): +(\w+) ?;`)
|
||||
vs := re.FindAllStringSubmatch(eg, -1)
|
||||
log.Println(vs)
|
||||
}
|
||||
|
||||
func toCamelCase(s string) string {
|
||||
var sb strings.Builder
|
||||
capitalizeNext := true
|
||||
for _, r := range s {
|
||||
if r == '_' || r == '/' || r == '-' {
|
||||
capitalizeNext = true
|
||||
} else if capitalizeNext {
|
||||
sb.WriteRune(unicode.ToUpper(r))
|
||||
capitalizeNext = false
|
||||
} else {
|
||||
sb.WriteRune(unicode.ToLower(r))
|
||||
}
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
9
server/app/internal/handlers/types_gen.tpl
Normal file
9
server/app/internal/handlers/types_gen.tpl
Normal file
@@ -0,0 +1,9 @@
|
||||
package actions
|
||||
|
||||
{{- range .}}
|
||||
type {{.ParamStruct.ParamStructName}} struct {
|
||||
{{- range .ParamStruct.ParamFields}}
|
||||
{{.ParamNameCamel}} {{.ParamType}} `json:"{{.ParamName}}" form:"{{.ParamName}}" binding:"{{.ParamBinding}}"`
|
||||
{{- end}}
|
||||
}
|
||||
{{end}}
|
||||
27
server/app/main.go
Normal file
27
server/app/main.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/iapologizewhenimwrong/Vestmore_GO/server/app/internal/handlers"
|
||||
)
|
||||
|
||||
func AppV10(ctx *gin.Context) {
|
||||
if actionKey, ok := ctx.GetPostForm("action"); ok {
|
||||
handlers.HandlersFuncRoutes[actionKey](ctx)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
r := gin.Default()
|
||||
v10 := r.Group("app")
|
||||
|
||||
v10.POST("/1_0", AppV10)
|
||||
|
||||
for k := range handlers.HandlersFuncRoutes {
|
||||
log.Printf("api %s", k)
|
||||
}
|
||||
|
||||
r.Run(":8080")
|
||||
}
|
||||
7
server/app/main_test.go
Normal file
7
server/app/main_test.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestMain(t *testing.T) {
|
||||
main()
|
||||
}
|
||||
Reference in New Issue
Block a user