diff --git a/.gitignore b/.gitignore index 908f699..a98dad6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,44 @@ __debug_* *.7z *.tar *.zip -*.gz \ No newline at end of file +*.gz + + +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +bin/ +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +#vscode + +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +__debug_bin +__debug_bin* + +.idea +.vscode + +screenlog.* \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 7b71657..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/proto.iml b/.idea/proto.iml deleted file mode 100644 index 5e764c4..0000000 --- a/.idea/proto.iml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index e03dad9..0000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/goutils/proto_build/main.go b/goutils/proto_build/main.go index 86f87fb..cef85c7 100644 --- a/goutils/proto_build/main.go +++ b/goutils/proto_build/main.go @@ -54,10 +54,10 @@ func main() { if len(args) == 0 || args[0] == "service" { ServiceMain() - } else if args[0] == "gateway" { - GatewayMain() + } else if args[0] == "client" { + GenClientMain() } else { - log.Println("Invalid argument. Usage: go run main.go [service|gateway]") + log.Println("Invalid argument. Usage: go run main.go [service|client]") } } @@ -83,6 +83,10 @@ func ServiceMain() { defer createFileNotExists("protoc.sh", 0755, func(f io.Writer) error { shellstr := `#! /bin/bash +if [ ! -d "proto" ] || [ -z "$(ls -A proto)" ]; then + git submodule init + git submodule update +fi go run -gcflags="-N" proto/goutils/proto_build/main.go` f.Write([]byte(shellstr)) return nil @@ -104,35 +108,26 @@ go run -gcflags="-N" proto/goutils/proto_build/main.go` // log.Println("Found proto folder at:", workerSpaceDir, ServiceNames, projectLastName, projectName) } -func GatewayMain() { +func GenClientMain() { log.Println("项目目录:", workspaceDir) checkProtoMessageName(workspaceDir + "/" + "proto/service") packageName := "service" - ServerCodePath := "server" + genDir := "gen/go" - ServiceName, projectName, projectLastName := getServiceNameAndProjectName(ServerCodePath) - if ServiceName == "" { - err := os.MkdirAll("server", 0755) - if err != nil { - log.Println(err) - } - createFileWithPermNotExists("server/service_config.ini", func(f io.Writer) error { - return tpl.ExecuteTemplate(f, "service_config.tpl", nil) - }) - panic("必须填写server/service_config.ini文件的项目名称与proto对应名称") - } defer createFileNotExists("protoc.sh", 0755, func(f io.Writer) error { shellstr := `#! /bin/bash -go run -gcflags="-N" proto/goutils/proto_build/main.go gateway` +if [ ! -d "proto" ] || [ -z "$(ls -A proto)" ]; then + git submodule init + git submodule update +fi +go run -gcflags="-N" proto/goutils/proto_build/main.go client` f.Write([]byte(shellstr)) return nil }) - // genDir := fmt.Sprintf("gen/go/%s", PackageName) - serviceProtoDir := fmt.Sprintf("proto/%s", packageName) err := os.MkdirAll(genDir+"/"+packageName, 0755) @@ -140,10 +135,16 @@ go run -gcflags="-N" proto/goutils/proto_build/main.go gateway` log.Println(err) } + projectName := "gitlab.fusenpack.com/backend/grpc" + + CheckGomodBasicPackage() ExecProtoc(workspaceDir, serviceProtoDir, genDir, packageName, projectName) + GitignoreGenCheck() ExecCreateAutoGrpc(genDir, packageName) - ExecCreateConfig(ServiceName, projectLastName) - ExecCreateGatewayAutoGrpc(genDir, packageName, projectLastName) + + createFileNotExists("update_fspkg_master.sh", 0755, func(f io.Writer) error { + return tpl.ExecuteTemplate(f, "update_fspkg_master.tpl", nil) + }) } func ExecCreateConfig(ServiceName, ProjectName string) { @@ -212,7 +213,7 @@ func ExecProtoc(workerSpaceDir, serviceProtoDir, genDir, packageName string, pro allServiceNames := getAllServiceName() - protoCmdStr := fmt.Sprintf(`protoc -I %s --go_out %s --go_opt paths=source_relative --go-grpc_out %s --go-grpc_opt paths=source_relative --grpc-gateway_out %s --grpc-gateway_opt paths=source_relative`, "proto", genDir, genDir, genDir) + protoCmdStr := fmt.Sprintf(`protoc -I %s --go_out %s --go_opt paths=source_relative --go-grpc_out %s --go-grpc_opt paths=source_relative `, "proto", genDir, genDir) for _, sname := range allServiceNames { protoCmdStr += importFileCmdStr(serviceNameEncode(packageName, sname), projectName) } @@ -298,15 +299,41 @@ func ExecCreateAutoLogic(workerSpaceDir string, ServiceName string, genDir, pack for _, info := range infos { // logicStructNames = append(logicStructNames, info.StructName) - var methods []map[string]string + var methods []map[string]interface{} for _, met := range info.Method { + var dup map[string]bool = make(map[string]bool) - methodMap := map[string]string{ + var paramsName []string + var paramsAndType []string + for i, param := range met.Params { + var p string + if param == "context.Context" { + dup["ctx"] = true + p = "ctx" + } else { + plist := strings.Split(param, ".") + lowerName := strings.ToLower(plist[len(plist)-1]) + if strings.Contains(lowerName, "req") { + if _, ok := dup["ctx"]; ok { + p = "req" + } + } + if _, ok := dup[p]; ok { + p = fmt.Sprintf("param%d", i) + } + } + param = p + " " + param + paramsAndType = append(paramsAndType, param) + paramsName = append(paramsName, p) + } + + methodMap := map[string]interface{}{ "StructName": info.StructName, + "MethodType": met.MethodType, "MethodName": met.MethodName, - "ParamCtx": met.Params[0], - "ParamReq": met.Params[1], + "ParamsName": paramsName, + "Params": paramsAndType, "MethodReturn": met.Returns[0], "MethodResponse": met.Returns[0][1:], } @@ -347,8 +374,9 @@ func ExecCreateAutoLogic(workerSpaceDir string, ServiceName string, genDir, pack // log.Println(genTypesBuffer.String()) formatted, err := format.Source(genTypesBuffer.Bytes()) if err != nil { - log.Printf("格式化代码失败:%v\n", err) - return + log.Println(genTypesBuffer.String()) + // panic(fmt.Sprintf("格式化代码失败:%v\n", err)) + formatted = genTypesBuffer.Bytes() } _, err = f.Write(formatted) @@ -369,7 +397,7 @@ func ExecCreateAutoLogic(workerSpaceDir string, ServiceName string, genDir, pack ss.StructServiceName = info.ServiceName for _, method := range methods { - fileName := convertToSnakeCase(method["MethodName"]) + fileName := convertToSnakeCase(method["MethodName"].(string)) method["ProjectName"] = projectName method["PackageName"] = logicPackageName createFileWithPermNotExists(fmt.Sprintf("%s/%s_logic.go", logicPath, fileName), func(f io.Writer) error { @@ -390,15 +418,15 @@ func ExecCreateTest(genDir, projectName, packageName, serviceName string) { genDir = genDir + "/" + packageName - var struCollection []*HttpGrpcMethodTest - for _, gwPath := range getSuffixFilesPath(genDir, strings.ToLower(serviceName)+".pb.gw.go") { + var struCollection []*GrpcMethodTest + for _, gwPath := range getSuffixFilesPath(genDir, strings.ToLower(serviceName)+"_grpc.pb.go") { struCollection = append(struCollection, genGatewayTestFunction(gwPath)...) } var buf bytes.Buffer err := tpl.ExecuteTemplate(&buf, "http_grpc_method_test.tpl", map[string]any{ - "ProjectName": projectName, - "HttpGrpcTestStructs": struCollection, + "ProjectName": projectName, + "GrpcTestStructs": struCollection, }) if err != nil { panic(err) @@ -711,16 +739,15 @@ func genGatewayWithNacosFunction(grpcPath string, gatewayBuf *bytes.Buffer) (fun return } -type HttpGrpcMethodTest struct { +type GrpcMethodTest struct { RequestVar string RequestStruct string + Params []string MethodName string - HttpMethod string - UrlPath string ServiceName string } -func genGatewayTestFunction(grpcPath string) (createdCollection []*HttpGrpcMethodTest) { +func genGatewayTestFunction(grpcPath string) (createdCollection []*GrpcMethodTest) { // workerSpaceDir+"/gen/go/service/auth_grpc.pb.go" // 解析Go源文件 fset := token.NewFileSet() @@ -730,73 +757,71 @@ func genGatewayTestFunction(grpcPath string) (createdCollection []*HttpGrpcMetho os.Exit(1) } + // var i = 0 for _, decl := range node.Decls { // 检查是否是接口声明 - if fdec, ok := decl.(*ast.FuncDecl); ok && fdec.Name.IsExported() && strings.HasSuffix(fdec.Name.Name, "HandlerServer") { + if fdec, ok := decl.(*ast.GenDecl); ok && fdec.Tok == token.TYPE { + // ast.Print(fset, fdec) + for _, spec := range fdec.Specs { + if typeSpec, ok := spec.(*ast.TypeSpec); ok && strings.HasSuffix(typeSpec.Name.Name, "Server") && !strings.HasPrefix(typeSpec.Name.Name, "Unsafe") && !strings.Contains(typeSpec.Name.Name, "_") { - created := &HttpGrpcMethodTest{} - // 修改函数执行内容 - ast.Inspect(fdec.Body, func(n ast.Node) bool { + serviceName := typeSpec.Name.Name + serviceName = serviceName[:len(serviceName)-6] + ast.Inspect(typeSpec, func(interfaceNode ast.Node) bool { - if callExpr, ok := n.(*ast.CallExpr); ok { + if methodDecl, ok := interfaceNode.(*ast.Ident); ok && methodDecl.IsExported() { + // log.Println(ftype.) + if methodDecl.Obj != nil { + if methodDecl.Obj.Kind == ast.Fun { + // log.Println(typeSpec.Name.Name) + // log.Println(methodDecl.Name) - if expr, ok := callExpr.Fun.(*ast.Ident); ok && strings.HasPrefix(expr.Name, "local_request") { - // log.Println(expr.Obj.Decl.(*ast.FuncDecl)) + created := GrpcMethodTest{} - created.ServiceName = strings.Split(expr.Name, "_")[2] - - ast.Inspect(expr.Obj.Decl.(*ast.FuncDecl).Body, func(n ast.Node) bool { - - if protoValue, ok := n.(*ast.ValueSpec); ok && protoValue.Names[0].Name == "protoReq" { - // log.Println(getTypeString(protoValue.Type)) - created.RequestStruct = getTypeString(protoValue.Type) - - } - - if expr, ok := n.(*ast.SelectorExpr); ok { - if exprServer, ok := expr.X.(*ast.Ident); ok && exprServer.Name == "server" { - // log.Println(expr.Sel.Name, expr.X) - created.MethodName = expr.Sel.Name - createdCollection = append(createdCollection, created) + created.ServiceName = serviceName + created.MethodName = methodDecl.Name created.RequestVar = "var" + created.MethodName + "Req" + field := methodDecl.Obj.Decl.(*ast.Field) + ftype := field.Type.(*ast.FuncType) + if len(ftype.Params.List) == 2 { + if reqstruct, ok := ftype.Params.List[1].Type.(*ast.StarExpr); ok { + rname := reqstruct.X.(*ast.Ident) + created.RequestStruct = rname.Name + createdCollection = append(createdCollection, &created) + } + } + // ast.Print(fset, ftype) - created = &HttpGrpcMethodTest{} - return false - } - - } - - return true - }) - - return true - } - - // log.Println(callExpr.Fun) - // getTypeString(callExpr.Fun) - if expr, ok := callExpr.Fun.(*ast.SelectorExpr); ok && expr.Sel.Name == "Handle" { - - var x = callExpr.Args[0].(*ast.BasicLit) - // log.Println(x, x.Value) - created.HttpMethod = x.Value - ast.Inspect(callExpr, func(n ast.Node) bool { - if callExprHandler, ok := n.(*ast.CallExpr); ok { - if expr, ok := callExprHandler.Fun.(*ast.SelectorExpr); ok && expr.Sel.Name == "WithHTTPPathPattern" { - var x = callExprHandler.Args[0].(*ast.BasicLit) - created.UrlPath = x.Value } } - return true - }) + } + + // ast.Print(fset, n) + // i++ + // log.Println(i) + // if i == 7 { + // log.Println() + // } + // printer.Fprint(os.Stdout, fset, n) + // io.WriteString(os.Stdout, "\n") + // if ftype, ok := n.(*ast.FuncType); ok { + // log.Println(getTypeString(ftype)) + // ast.Print(fset, ftype) + // } + return true - } + }) } - return true - }) + } + + // created.RequestVar = "var" + created.MethodName + "Req" + + // 修改函数执行内容 } + } return @@ -848,7 +873,7 @@ func getGrpcFileClientNames(genDir string) (result []*ClientParam) { } func importFileCmdStr(importFile string, projectName string) string { - shellStr := " {{.ImportFile}} --go_opt=M{{.ImportFile}}={{.ProjectName}} --go-grpc_opt=M{{.ImportFile}}={{.ProjectName}} --grpc-gateway_opt=M{{.ImportFile}}={{.ProjectName}} " + shellStr := " {{.ImportFile}} --go_opt=M{{.ImportFile}}={{.ProjectName}} --go-grpc_opt=M{{.ImportFile}}={{.ProjectName}}" tmpl, err := template.New("shell").Parse(shellStr) if err != nil { @@ -870,6 +895,7 @@ func importFileCmdStr(importFile string, projectName string) string { log.Printf("模板执行失败:%v\n", err) return "" } + // log.Println(buf.String()) return buf.String() } @@ -923,7 +949,9 @@ func getAllServiceName() (result []string) { panic(err) } for _, e := range dirEntrys { - result = append(result, e.Name()[0:len(e.Name())-6]) + if filepath.Ext(e.Name()) == ".proto" { + result = append(result, e.Name()[0:len(e.Name())-6]) + } } return } @@ -1055,9 +1083,23 @@ func parseGoFile(filePath string) (ClientParams []*ClientParam) { // fieldName := field.Names[0].Name // log.Println("Field:", fieldName) } - } else if _, ok := typeSpec.Type.(*ast.InterfaceType); ok { + } else if iface, ok := typeSpec.Type.(*ast.InterfaceType); ok { interfaceName := typeSpec.Name.Name + if len(iface.Methods.List) >= 3 { + if len(iface.Methods.List[2].Names) == 0 { + + // log.Println(name0, name1) + if getTypeString(iface.Methods.List[2].Type) == "grpc.ClientStream" { + // MethodType = "stream" + // log.Println(interfaceName) + + continue + } + + } + } + if strings.HasSuffix(interfaceName, "Client") { Param.ClientName = interfaceName[0 : len(interfaceName)-6] } @@ -1084,6 +1126,7 @@ func parseGoFile(filePath string) (ClientParams []*ClientParam) { type GrpcServerMethod struct { MethodName string + MethodType string Params []string Returns []string } @@ -1123,10 +1166,30 @@ func ParseGrpcServerInfo(grpcPath string) (infos []*GrpcServerInfo) { continue } + if strings.Contains(ifaceSpec.Name.Name, "_") { + continue + } + if strings.HasPrefix(ifaceSpec.Name.Name, "Unsafe") { continue } + if len(ifaceType.Methods.List) == 3 { + if len(ifaceType.Methods.List[0].Names) == 1 && len(ifaceType.Methods.List[1].Names) == 1 { + name0 := ifaceType.Methods.List[0].Names[0].Name + name1 := ifaceType.Methods.List[1].Names[0].Name + if name0 == "SendAndClose" && name1 == "Recv" { + // log.Println(name0, name1) + if getTypeString(ifaceType.Methods.List[2].Type) == "grpc.ServerStream" { + // MethodType = "stream" + continue + } + + } + + } + } + ServiceName := ifaceSpec.Name.Name[0 : len(ifaceSpec.Name.Name)-6] info := &GrpcServerInfo{ ServiceName: ServiceName, @@ -1139,29 +1202,40 @@ func ParseGrpcServerInfo(grpcPath string) (infos []*GrpcServerInfo) { // 打印接口方法 for _, method := range ifaceType.Methods.List { + if len(method.Names) == 0 { + continue + } + if !isUpper(method.Names[0].Name) { continue } - m := &GrpcServerMethod{} + m := &GrpcServerMethod{ + MethodType: "rpc", + } info.Method = append(info.Method, m) // 方法名称 // log.Println("方法名:", method.Names[0].Name) // MethodName := method.Names[0].Name m.MethodName = method.Names[0].Name // 方法参数 - if len(method.Type.(*ast.FuncType).Params.List) > 0 { - // log.Println("参数:") - // params := method.Type.(*ast.FuncType).Params - // log.Println(params.NumFields(), params.List) - // log.Println(string(src[method.Pos()-1 : method.End()-1])) - - for _, field := range method.Type.(*ast.FuncType).Params.List { + mparams := method.Type.(*ast.FuncType).Params.List + switch len(mparams) { + case 2: + for _, field := range mparams { // log.Printf("%s %s\n", field.Names, getTypeString(field.Type, packageName, 0)) m.Params = append(m.Params, getTypeString(field.Type, packageName)) } - } else { + case 1: + m.MethodType = "stream" + for _, field := range mparams { + // log.Printf("%s %s\n", field.Names, getTypeString(field.Type, packageName, 0)) + m.Params = append(m.Params, getTypeString(field.Type, packageName)) + } + case 0: log.Println("无参数") + default: + panic("诡异的结构") } // 方法返回值 @@ -1468,3 +1542,28 @@ func getGrpcFileServiceName(decl ast.Decl) (string, string, bool) { } return "", "", false } + +// 检测gitignore gen是否存在 +func GitignoreGenCheck() { + + gitignoreFile := "./.gitignore" + + data, err := os.ReadFile(gitignoreFile) + if err != nil { + log.Println(err.Error()) + return + } + + for _, line := range strings.Split(string(data), "\n") { + if strings.Trim(line, " ") == "gen" { + return + } + } + + data = append(data, []byte("\ngen\n")...) + + err = os.WriteFile(gitignoreFile, data, 0644) + if err != nil { + panic(err) + } +} diff --git a/goutils/proto_build/main_test.go b/goutils/proto_build/main_test.go index e7727b1..fe7fe53 100644 --- a/goutils/proto_build/main_test.go +++ b/goutils/proto_build/main_test.go @@ -9,5 +9,5 @@ func TestMain(t *testing.T) { } func TestGateway(t *testing.T) { - GatewayMain() + GenClientMain() } diff --git a/goutils/proto_build/tpls/auto_grpc_gateway_nacos.tpl b/goutils/proto_build/tpls/auto_grpc_gateway_nacos.tpl deleted file mode 100644 index 36f5fc9..0000000 --- a/goutils/proto_build/tpls/auto_grpc_gateway_nacos.tpl +++ /dev/null @@ -1,10 +0,0 @@ -package service - -import ( - "context" - "net/http" - - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "google.golang.org/grpc" -) - diff --git a/goutils/proto_build/tpls/auto_grpc_gateway_register.tpl b/goutils/proto_build/tpls/auto_grpc_gateway_register.tpl deleted file mode 100644 index f823a8d..0000000 --- a/goutils/proto_build/tpls/auto_grpc_gateway_register.tpl +++ /dev/null @@ -1,20 +0,0 @@ -package logic - -import ( - "context" - "{{.ProjectName}}/gen/go/service" - - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "google.golang.org/grpc" -) - -func AutoRegisterHandler(ctx context.Context, mux *runtime.ServeMux, opts ...grpc.DialOption) error { - var err error - {{range .FuncNames}} - err = service.{{.}}(ctx, mux, opts...) - if err != nil { - return err - } - {{end}} - return nil -} diff --git a/goutils/proto_build/tpls/auto_grpc_nacos.tpl b/goutils/proto_build/tpls/auto_grpc_nacos.tpl index 6233c14..9cdb510 100644 --- a/goutils/proto_build/tpls/auto_grpc_nacos.tpl +++ b/goutils/proto_build/tpls/auto_grpc_nacos.tpl @@ -4,6 +4,7 @@ import ( "fmt" "log" "reflect" + "fusen-basic/env" "github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client" "github.com/nacos-group/nacos-sdk-go/v2/vo" @@ -14,6 +15,10 @@ import ( var namingClient naming_client.INamingClient var groupName string +func init() { + AutoGrpcInit(env.StartAutoGrpc()) +} + // AutoGrpcInit auto grpc 必须调用初始化 func AutoGrpcInit(obj any) { value := reflect.ValueOf(obj) diff --git a/goutils/proto_build/tpls/http_grpc_method_file_test.tpl b/goutils/proto_build/tpls/http_grpc_method_file_test.tpl index 66c4934..3af3c26 100644 --- a/goutils/proto_build/tpls/http_grpc_method_file_test.tpl +++ b/goutils/proto_build/tpls/http_grpc_method_file_test.tpl @@ -11,15 +11,7 @@ func init() { {{.RequestVar}} = &service.{{.RequestStruct}}{} } -func Test{{.MethodName}}HTTP(t *testing.T) { - // 构建请求体 - resp, err := {{.MethodName}}Http(nil) - if err != nil { - t.Error(err) - } - log.Println(resp) -} - + func Test{{.MethodName}}RPC(t *testing.T) { resp, err := {{.MethodName}}RPC() if err != nil { diff --git a/goutils/proto_build/tpls/http_grpc_method_test.tpl b/goutils/proto_build/tpls/http_grpc_method_test.tpl index 105722d..86bc486 100644 --- a/goutils/proto_build/tpls/http_grpc_method_test.tpl +++ b/goutils/proto_build/tpls/http_grpc_method_test.tpl @@ -2,26 +2,15 @@ package test import ( "context" - "net/http" "{{.ProjectName}}/gen/go/service" "{{.ProjectName}}/server/config" "fusen-basic/env" ) -{{range .HttpGrpcTestStructs}} +{{range .GrpcTestStructs}} var {{.RequestVar}} *service.{{.RequestStruct}} - -func {{.MethodName}}Http(reqHandler func(*http.Request) error) (any, error) { - resp, err := HttpRequest({{.HttpMethod}}, gatewayAddrress+{{.UrlPath}}, {{.RequestVar}}, reqHandler) - if err != nil { - // t.Error(err) - return nil, err - } - return resp, nil -} - func {{.MethodName}}RPC() (any, error) { if fusen == nil { fusen := env.NewFusenTest[config.Config]() diff --git a/goutils/proto_build/tpls/http_grpc_method_var.tpl b/goutils/proto_build/tpls/http_grpc_method_var.tpl index 99e850a..99914d6 100644 --- a/goutils/proto_build/tpls/http_grpc_method_var.tpl +++ b/goutils/proto_build/tpls/http_grpc_method_var.tpl @@ -1,104 +1,9 @@ package test import ( - "bytes" - "encoding/json" - "fmt" "{{.ProjectName}}/server/config" "fusen-basic/env" - "fusen-basic/utils/log" - "net/http" - "net/url" - "reflect" - "strings" - "time" ) var fusen *env.Fusen[config.Config] -var gatewayAddrress = "http://localhost:9900" - - -func HttpRequest(method, urlStr string, body interface{}, reqHandler func(*http.Request) error) (map[string]interface{}, error) { - var jsonBody *bytes.Buffer - var queryParams url.Values - if method == "GET" { - queryParams = JsonTagToURLValues(body) - jsonBody = bytes.NewBuffer(nil) - } else { - // 将请求体转换为JSON格式 - jsonData, err := json.Marshal(body) - if err != nil { - log.Printf("Failed to marshal request body: %s\n", err.Error()) - return nil, err - } - jsonBody = bytes.NewBuffer(jsonData) - log.Println(string(jsonData)) - } - - // 创建URL对象并添加查询参数 - u, err := url.Parse(urlStr) - if err != nil { - fmt.Printf("Failed to parse URL: %s\n", err.Error()) - return nil, err - } - u.RawQuery = queryParams.Encode() - // 创建HTTP请求 - req, err := http.NewRequest(method, u.String(), jsonBody) - if err != nil { - fmt.Printf("Failed to create HTTP request: %s\n", err.Error()) - return nil, err - } - - // 设置请求头 - req.Header.Set("Content-Type", "application/json") - - if reqHandler != nil { - reqHandler(req) - } - - // 发送HTTP请求 - client := http.DefaultClient - client.Timeout = time.Second * 60 - resp, err := client.Do(req) - if err != nil { - fmt.Printf("HTTP request failed: %s\n", err.Error()) - return nil, err - } - - if resp.StatusCode != 200 { - return nil, fmt.Errorf("%s", resp.Status) - } - - defer resp.Body.Close() - - // 解析响应体 - var response map[string]interface{} - err = json.NewDecoder(resp.Body).Decode(&response) - if err != nil { - fmt.Printf("Failed to decode response body: %s\n", err.Error()) - return nil, err - } - return response, nil -} - -func JsonTagToURLValues(body interface{}) url.Values { - values := url.Values{} - - v := reflect.ValueOf(body) - if v.Kind() == reflect.Ptr { - v = v.Elem() - } - t := v.Type() - - for i := 0; i < t.NumField(); i++ { - field := t.Field(i) - if field.IsExported() { - if jsonTag, ok := field.Tag.Lookup("json"); ok { - jtag := strings.Split(jsonTag, ",")[0] - value := v.Field(i).String() - values.Set(jtag, value) - } - } - } - return values -} \ No newline at end of file +var gatewayAddrress = "http://localhost:9900" \ No newline at end of file diff --git a/goutils/proto_build/tpls/logic_fusen_handler.tpl b/goutils/proto_build/tpls/logic_fusen_handler.tpl index f1819a3..6ac34b8 100644 --- a/goutils/proto_build/tpls/logic_fusen_handler.tpl +++ b/goutils/proto_build/tpls/logic_fusen_handler.tpl @@ -1,16 +1,24 @@ package {{.PackageName}} import ( - "fusen-basic/basic" +{{if eq .MethodType "rpc"}} + "context" +{{end}} "{{.ProjectName}}/gen/go/service" ) -func (l *{{.StructName}}) {{.MethodName}}Logic(req {{.ParamReq}}, userinfo *basic.UserInfo) (resp *basic.Response[{{.MethodResponse}}]) { - return resp.Set(basic.CodeOK) +{{if eq .MethodType "rpc"}} + +func (l *{{.StructName}}) {{.MethodName}}Logic({{range $index, $param := .Params}}{{if $index}}, {{end}}{{$param}}{{end}}) (resp {{.MethodReturn}},err error) { + resp = &{{.MethodResponse}}{} + return resp, nil } +{{else if eq .MethodType "stream"}} + +func (l *{{.StructName}}) {{.MethodName}}Logic(stream {{range $index, $param := .Params}}{{if $index}}, {{end}}{{$param}}{{end}}) (err error) { + return nil +} + +{{end}} -// 自定义验证校验方法 VaildUserInfoHandler -// func (h *{{.MethodName}}Handler) VaildUserInfoHandler(ctx context.Context) *basic.UserInfo { -// return basic.ValidUserInfo(ctx) -// } diff --git a/goutils/proto_build/tpls/logic_grpc_struct.tpl b/goutils/proto_build/tpls/logic_grpc_struct.tpl index 8f8f1c6..408c23f 100644 --- a/goutils/proto_build/tpls/logic_grpc_struct.tpl +++ b/goutils/proto_build/tpls/logic_grpc_struct.tpl @@ -3,17 +3,13 @@ package {{.PackageName}} import ( "context" - "strings" "sync" + "fmt" - "fusen-basic/basic" "fusen-basic/env" - "fusen-basic/utils/log" - + "{{.ProjectName}}/gen/go/service" "{{.ProjectName}}/server/config" - - "google.golang.org/grpc/metadata" ) @@ -50,80 +46,30 @@ type {{.MethodName}}Handler struct { type {{.MethodName}}HandlerMust struct{} -func (must *{{.MethodName}}HandlerMust) ValidUserInfoHandler(ctx context.Context) *basic.UserInfo { - return defaultValidUserInfoHandler(ctx) +{{if eq .MethodType "rpc"}} + +func (lgrpc *{{.StructName}}Grpc) {{.MethodName}}({{range $index, $param := .Params}}{{if $index}}, {{end}}{{$param}}{{end}}) (_resp {{.MethodReturn}},_err error) { + defer func() { + if _recoverErr := recover(); _recoverErr != nil { + _resp = nil + _err = fmt.Errorf("%v", _recoverErr) + } + }() + return New{{.StructName}}(ctx).{{.MethodName}}Logic({{range $index, $param := .ParamsName}}{{if $index}}, {{end}}{{$param}}{{end}}) } -var __hide_handler{{.MethodName}} *{{.MethodName}}Handler = &{{.MethodName}}Handler{} +{{else if eq .MethodType "stream"}} -func (lgrpc *{{.StructName}}Grpc) {{.MethodName}}(ctx {{.ParamCtx}}, req {{.ParamReq}}) ({{.MethodReturn}}, error) { - return New{{.StructName}}(ctx).{{.MethodName}}Logic(req, __hide_handler{{.MethodName}}.ValidUserInfoHandler(ctx)).PassMetaResponse(ctx) +func (lgrpc *{{.StructName}}Grpc) {{.MethodName}}(stream {{range $index, $param := .Params}}{{if $index}}, {{end}}{{$param}}{{end}}) (_err error) { + defer func() { + if _recoverErr := recover(); _recoverErr != nil { + _err = fmt.Errorf("%v", _recoverErr) + } + }() + return New{{.StructName}}(stream.Context()).{{.MethodName}}Logic(stream) } {{end}} -func DefaultValidToken(ctx context.Context) *basic.UserInfo { - var ( - err error - ui = &basic.UserInfo{} - ) - // log.Println(ctx) - if md, ok := metadata.FromIncomingContext(ctx); ok { - var authtoken, debugtoken *string - var vresult *service.ValidTokenResponse - if a, ok := md["authorization"]; ok { - token := a[0] - if len(token) > 15 { - if strings.HasPrefix(token[1:], "earer ") { - token = token[7:] - } - authtoken = &token - defer func() { - if vresult != nil { - userinfo := vresult.UserInfo.AsMap() - if len(userinfo) != 0 { - ui.UserId = int64(userinfo["user_id"].(float64)) - ui.GuestId = int64(userinfo["guest_id"].(float64)) - ui.Exp = int64(userinfo["exp"].(float64)) - } - } - }() - } - - } - - if a, ok := md["debug-token"]; ok { - token := a[0] - if len(token) > 15 { - if strings.HasPrefix(token[1:], "earer ") { - token = token[7:] - } - debugtoken = &token - - defer func() { - if vresult != nil { - debug := vresult.DebugInfo.AsMap() - if len(debug) != 0 { - ui.Debug = &basic.Debug{} - if dexp, ok := debug["exp"]; ok { - dexpint64 := int64(dexp.(float64)) - ui.Debug.Exp = &dexpint64 - } - ui.Debug.IsAllTemplateTag = int64(debug["is_all_template_tag"].(float64)) - ui.Debug.IsCache = int64(debug["is_cache"].(float64)) - } - } - }() - } - } - - vresult, err = service.AutoAuthClient(ctx).ValidToken(context.TODO(), &service.ValidTokenRequest{ - UserToken: authtoken, - DebugToken: debugtoken, - }) - if err != nil { - log.Println(err.Error()) - } - } - return ui -} \ No newline at end of file +{{end}} + \ No newline at end of file diff --git a/goutils/proto_build/tpls/logic_init.tpl b/goutils/proto_build/tpls/logic_init.tpl index 79eb418..4a177dd 100644 --- a/goutils/proto_build/tpls/logic_init.tpl +++ b/goutils/proto_build/tpls/logic_init.tpl @@ -3,16 +3,12 @@ package {{.PackageName}} import ( "context" - "fusen-basic/basic" "fusen-model/dbutils" "fusen-model/gmodel" "{{.ProjectName}}/server/config" ) -// 统一的验证入口 -var defaultValidUserInfoHandler func(context.Context) *basic.UserInfo = DefaultValidToken - // 处理共享数据的上下文 type SharedContext struct { models *gmodel.Models diff --git a/goutils/proto_build/tpls/main.tpl b/goutils/proto_build/tpls/main.tpl index e97338e..d2e33f6 100644 --- a/goutils/proto_build/tpls/main.tpl +++ b/goutils/proto_build/tpls/main.tpl @@ -10,10 +10,6 @@ import ( "{{.ProjectName}}/server/config" - {{range .LogicDirNames}} - "{{$.ProjectName}}/{{.}}" - {{- end}} - "google.golang.org/grpc" ) @@ -21,7 +17,6 @@ func main() { fusen := env.NewFusen[config.Config]() fusen.StartNacos(nil) - service.AutoGrpcInit(fusen) sopt := grpc.UnaryInterceptor(fusen.Interceptor()) diff --git a/goutils/tools.go b/goutils/tools.go index 0044412..a9857d7 100644 --- a/goutils/tools.go +++ b/goutils/tools.go @@ -9,9 +9,9 @@ package goutils // google.golang.org/protobuf/cmd/protoc-gen-go \ // google.golang.org/grpc/cmd/protoc-gen-go-grpc -import ( - _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway" - _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2" - _ "google.golang.org/grpc/cmd/protoc-gen-go-grpc" - _ "google.golang.org/protobuf/cmd/protoc-gen-go" -) +// import ( +// _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway" +// _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2" +// _ "google.golang.org/grpc/cmd/protoc-gen-go-grpc" +// _ "google.golang.org/protobuf/cmd/protoc-gen-go" +// ) diff --git a/service/auth.proto b/service/auth.proto index ae10948..4a70c86 100644 --- a/service/auth.proto +++ b/service/auth.proto @@ -14,113 +14,29 @@ import "google/protobuf/any.proto"; service auth { // 登录接口 - rpc ValidToken(ValidTokenRequest) returns (ValidTokenResponse) { - // 添加 HTTP POST 网关注解 - option (google.api.http) = { - post: "/api/auth/valid/token" - body: "*" - }; - } - - // 登录接口 - rpc Login(UserLoginRequest) returns (UserLoginResponse) { - // 添加 HTTP POST 网关注解 - option (google.api.http) = { - post: "/api/auth/login" - body: "*" - }; - } - - // 注册接口 - rpc Register(UserRegisterRequest) returns (basic.Response) { - // 添加 HTTP POST 网关注解 - option (google.api.http) = { - post: "/api/auth/register" - body: "*" - }; - } + rpc ValidToken(ValidTokenRequest) returns (ValidTokenResponse) {} // Cookie 接受接口 - rpc AcceptCookie(basic.Request) returns (GuestResponse) { - // 添加 HTTP POST 网关注解 - option (google.api.http) = { - post: "/api/auth/accept-cookie" - body: "*" - }; - } + rpc CreateAcceptCookie(basic.Request) returns (GuestResponse) {} // 调试令牌创建接口 - rpc CreateDebugToken(UserDebugRequest) returns (DebugTokenResponse) { - // 添加 HTTP POST 网关注解 - option (google.api.http) = { - post: "/api/auth/debug/token/create" - body: "*" - }; - } - - // Google 登录接口 - rpc GoogleLogin(GoogleLoginRequest) returns (basic.Response) { - // 添加 HTTP GET 网关注解 - option (google.api.http) = { - get: "/api/auth/oauth2/login/google" - }; - } - - // 邮箱确认接口 - rpc EmailConfirmation(EmailConfirmationRequest) returns (basic.Response) { - // 添加 HTTP GET 网关注解 - option (google.api.http) = { - post: "/api/auth/email/confirmation" - body: "*" - }; - } - - // 使用邮箱注册接口 - rpc EmailRegister(EmailRegisterRequest) returns (basic.Response) { - // 添加 HTTP POST 网关注解 - option (google.api.http) = { - post: "/api/auth/oauth2/register" - body: "*" - }; - } - - // 发送重置令牌到邮箱接口 - rpc ResetToken(UserResetTokenRequest) returns (basic.Response) { - // 添加 HTTP POST 网关注解 - option (google.api.http) = { - post: "/api/auth/reset/token" - body: "*" - }; - } - - // 重置密码接口 - rpc ResetPassword(UserResetPasswordRequest) returns (basic.Response) { - // 添加 HTTP POST 网关注解 - option (google.api.http) = { - post: "/api/auth/reset/password" - body: "*" - }; - } - - // 获取重定向到 HTML 页面接口 - rpc ResetPasswordHtml(UserResetHtmlRequest) returns (basic.Response) { - // 添加 HTTP GET 网关注解 - option (google.api.http) = { - get: "/api/auth/reset/password/html" - }; - } - - // 调试删除帐号接口 - rpc DebugDelete(AuthDeleteRequest) returns (basic.Response) { - // 添加 HTTP POST 网关注解 - option (google.api.http) = { - post: "/api/auth/debug/delete" - body: "*" - }; - } + rpc CreateDebugToken(UserDebugRequest) returns (DebugTokenResponse) {} } +message Debug { + int64 exp = 1; + int64 is_cache = 2; + int64 is_all_template_tag = 3; +} + +message UserInfo { + int64 user_id = 1; + int64 guest_id = 2; + int64 exp = 3; + Debug debug = 4; +} + // 验证token的请求 message ValidTokenRequest { optional string user_token = 1; @@ -130,8 +46,7 @@ message ValidTokenRequest { // 验证token的请求 message ValidTokenResponse { - google.protobuf.Struct user_info = 1; - google.protobuf.Struct debug_info = 2; + UserInfo user_info = 1; } diff --git a/service/basic.proto b/service/basic.proto index 28c99eb..443e886 100644 --- a/service/basic.proto +++ b/service/basic.proto @@ -17,4 +17,24 @@ message Response { } +message ResourceInfo{ + string resource_id = 1; + int64 guest_id =2; + int64 user_id =3; + string resource_type = 4; + string resource_url = 5; + string version = 6; + int64 api_type = 7; + string bucket_name = 8; + string source = 9; + string uploaded_at = 10; + google.protobuf.Struct metadata = 11; +} + +message Meta { + int64 total_count =1; + int64 page_count=2; + int64 current_page=3; + int64 per_page=4; +} \ No newline at end of file diff --git a/service/fsservice.proto b/service/fsservice.proto.bak similarity index 100% rename from service/fsservice.proto rename to service/fsservice.proto.bak diff --git a/service/notify.proto b/service/notify.proto index 2d5ed02..a2a8ca2 100644 --- a/service/notify.proto +++ b/service/notify.proto @@ -8,15 +8,163 @@ import "google/api/annotations.proto"; import "service/basic.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/any.proto"; +import "google/protobuf/empty.proto"; +import "google/api/httpbody.proto"; +import "google/protobuf/timestamp.proto"; //定义服务 service notify { + + // 心跳 + rpc Ping(basic.Request) returns (basic.Response) {} + + // 邮件发送基础版本 + rpc EmailSend(EmailSendReq) returns (EmailSendRes) {} - // 邮件注册确认 - rpc EmailRegisterConfirm(basic.Request) returns (basic.Response) { - option (google.api.http) = { - post: "/api/notify/email" - body: "*" - }; + // 邮件注册确认 + rpc EmailRegisterConfirm( EmailRegisterReq) returns ( EmailRegisterResp) {} + + // 邮件重置密码的填写页面 + rpc EmailResetPasswordHtml( EmailResetHtmlReq) returns (EmailResetHtmlResp) {} + + // 邮件重置密码的确认 + rpc EmailResetConfirm( EmailResetConfirmReq) returns (EmailResetConfirmResp) {} + + // 订单 支付详情 + rpc OrderPaymentDetails( OrderPaymentDetailsReq) returns (OrderPaymentDetailsResp) {} + + + // 订单 状态流转 + rpc OrderStatusTransition( OrderStatusTransitionReq) returns (OrderStatusTransitionResp) {} + + // 订单 状态流转 + rpc OrderPayArrears( OrderPayArrearsReq) returns (OrderPayArrearsResp) {} +} + + +message Operator { + + // 操作类型 + enum Type { + immediate_resend = 0; // 马上重发(覆盖当前的发送任务,等于重置) + normal_send = 1; // 标准发送(可以设置时间和重发的次数) + cancel_send = 2; // 取消发送(取消当前的发送) } + + message Retry { + int64 retry_count = 1; // 允许重发次数 + int64 interval_time = 2; // 执行的时间间隔 sec 用秒为单位 + + } + + Type type = 1; // 操作类型 + optional Retry retry = 2; //重试 + + optional google.protobuf.Timestamp start_time = 3; // 在这个时间开始执行 + optional google.protobuf.Timestamp last_send_time = 4; // 上次发送的时间 + } + +message EmailNotifyBasic { + optional string notify_id = 1; // 用于处理唯一的任务,重发都会被利用到 256字节 + string sender = 2; // 发送者 + string target_email = 3; // 发送的目标email +} + + +// 默认是 type email +message EmailSendReq { + EmailNotifyBasic basic_email = 1; + string title = 2; // 邮件标题 + string content = 3; // 邮件内容 + Operator operator = 4; // 操作类型 + optional google.protobuf.Struct metadata = 5; // 扩展参数 +} + +// 消息类型 +enum NotifyType { + email = 0; // email + feishu = 1; // 飞书 + wechat = 2; // 微信 +} + + +// 操作类型 +enum EmailStatus { + ok = 0; // 成功 + running = 1; // 进行中 + error = 2; // 处理错误 + cancel = 3; // 已经被取消 + finish = 4; // 结束 +} + + + +message EmailSendRes { + EmailStatus status = 1; + string msg = 2; +} + +message EmailRegisterReq { + EmailNotifyBasic basic_email = 1; + string confirmation_link = 2; +} + +message EmailRegisterResp { + int64 code = 1; // 0成功 其他异常 + string notify_id = 2; // 通知id +} + + +message EmailResetHtmlReq { + EmailNotifyBasic basic_email = 1; + string confirmation_link = 4; +} + +message EmailResetHtmlResp { + int64 code = 1; // 0成功 其他异常 + string notify_id = 2; // 通知id +} + +message EmailResetConfirmReq { + string reset_password_link = 1; + string reset_token = 2; +} + +message EmailResetConfirmResp { + int64 code = 1; // 0成功 其他异常 + bytes content = 2; // 返回页面内容 +} + + +message OrderPaymentDetailsReq { + EmailNotifyBasic basic_email = 1; + string payment_details_link = 2; +} + +message OrderPaymentDetailsResp { + int64 code = 1; // 0成功 其他异常 + string notify_id = 2; // 通知id +} + +message OrderStatusTransitionReq { + EmailNotifyBasic basic_email = 1; + string last_status = 2; // 上个状态 + string current_status = 3; // 当前状态 + string check_status_link = 4; // 检查状态 +} + +message OrderStatusTransitionResp { + int64 code = 1; // 0成功 其他异常 + string notify_id = 2; // 通知id +} + + +message OrderPayArrearsReq { + EmailNotifyBasic basic_email = 1; + string pay_arrears_link = 2; // 检查状态 +} + +message OrderPayArrearsResp { + int64 code = 1; // 0成功 其他异常 + string notify_id = 2; // 通知id } \ No newline at end of file diff --git a/service/resource.proto b/service/resource.proto index 8c3f064..8eb316c 100644 --- a/service/resource.proto +++ b/service/resource.proto @@ -11,52 +11,157 @@ import "google/protobuf/any.proto"; //定义服务 service resource { + // 删除资源详情 + rpc ResourceDelete(ResourceDeleteReq) returns (ResourceDeleteRes) {} + + // 更新资源详情 + rpc ResourceSave(ResourceSaveReq) returns (ResourceSaveRes) {} // 获取资源详情 - rpc GetResourceInfo(GetResourceInfoReq) returns (basic.Response) { - option (google.api.http) = { - get: "/api/resource/info" - }; - } + rpc ResourceInfo(ResourceInfoReq) returns (ResourceInfoRes) {} // 获取资源列表 - rpc GetResourceList(GetResourceListReq) returns (basic.Response) { - option (google.api.http) = { - get: "/api/resource/list" - }; - } + rpc ResourceList(ResourceListReq) returns (ResourceListRes) {} // 后端上传--单文件 - rpc UploadFileBackend(UploadFileBackendReq) returns (UploadFileBackendRes) { - option (google.api.http) = { - post: "/api/resource/upload-file-backend", - body: "*" - }; - } + rpc UploadFileBackend(UploadFileBackendReq) returns (UploadFileBackendRes) {} // 后端上传--分片上传 - rpc UploadFileBackendFragment(UploadFileBackendFragmentReq) returns (UploadFileBackendFragmentRes) { - option (google.api.http) = { - post: "/api/resource/upload-file-backend-fragment", - body: "*" - }; - } + rpc UploadFileBackendFragment(UploadFileBackendFragmentReq) returns (UploadFileBackendFragmentRes) {} + + // logo合图 + rpc LogoCombine(LogoCombineReq) returns (LogoCombineRes) {} + + // logo基础信息 + rpc LogoInfoSet(LogoInfoSetReq) returns (LogoInfoSetRes) {} + + // logo裁剪处理 + rpc LogoCropping(LogoCroppingReq) returns (LogoCroppingRes) {} + + // logo缩略处理 + rpc LogoResize(LogoResizeReq) returns (LogoResizeRes) {} + } +/* logo缩略处理 */ +message LogoResizeReq{ + string resource_id=1; + int64 width=2; + int64 height=3; + + int64 handle_type = 100; // 类型:1=缓存 2=重新 3=临时 + int64 user_id = 101; + int64 guest_id = 102; +} +message LogoResizeRes{ + string resource_id=1; + string resource_url=2; +} +/* logo缩略处理 */ + +/* 更新资源详情 */ +message ResourceSaveReq { + optional ResourceFilter filter=1; + optional ResourceFilter save=2; +} +message ResourceSaveRes {} +/* 更新资源详情 */ + +/* 删除资源详情 */ +message ResourceDeleteReq { + optional ResourceFilter filter=1; + + int64 delete_type = 12; // 删除类型:1=删除数据库 2=删除s3 3=删除数据库+s3 + int64 delete_limit = 13; // 删除数量 +} + +message ResourceDeleteRes {} +/* 删除资源详情 */ + +/* logo裁剪处理 */ +message LogoCroppingReq { + string is_remove_bg=1; + string logo_file=2; + string width=3; + string height=4; + string proportion=5; + + int64 handle_type = 100; // 类型:1=缓存 2=重新 3=临时 + int64 user_id = 101; + int64 guest_id = 102; +} +message LogoCroppingRes { + string resource_id=1; + string resource_url=2; + bool ismax_proportion=3; + repeated string img_color=4; +} +/* logo裁剪处理 */ + +/* logo基础信息 */ +message LogoInfoSetReq { + string logo_url=1; + string version=2; + int64 is_all_template=3; +} +message LogoInfoSetRes { + string info =1; +} +/* logo基础信息 */ + +/* logo合图 */ +message LogoCombineReq { + int64 product_template_v2_info_id =1; + string product_template_v2_info_material_img =2; + string product_template_v2_info_template_info =3; + string template_tag =4; + string website=5; + string slogan=6; + string address=7; + string phone=8; + string qrcode=9; + string logo_url=10; + string resolution=11; + TemplateTagColor template_tag_color=12; + string logo_metadata=13; + repeated TemplateTagGroups template_tag_groups=14; + + int64 handle_type = 100; // 类型:1=缓存 2=重新 3=临时 + int64 user_id = 101; + int64 guest_id = 102; +} +message TemplateTagColor { + repeated Color color =1; + int64 index = 2; +} +message Color { + repeated string names = 1; +} +message TemplateTagGroups { + string tag =1; + string name =2; + string value =3; + int64 fixed =4; +} +message LogoCombineRes { + string resource_id = 4; + string resource_url = 6; + int64 diff_time_logo_combine=15; // 合图算法时间 + int64 diff_time_upload_file=16; // 合图上传时间 +} +/* logo合图 */ + /* 后端上传--分片上传 */ message UploadFileBackendFragmentReq { string file_name = 1; // 文件名 - bytes file_content = 2; // 文件流 - bytes file_header = 3; // 文件头 - string file_data = 4; // base64 + bytes file_content = 3; // 文件流 + bytes file_header = 4; // 文件头 + string file_data = 5; // base64 + int64 chunk_number = 6; // 当前分片号:1、2、3 + int64 total_chunks = 7; // 总分片数:3 - int64 chunk_number = 5; // 当前分片号:1、2、3 - int64 total_chunks = 6; // 总分片数:3 - int64 user_id = 7; - int64 guest_id = 8; - - int64 api_type = 10; // 请求类型:1=对外,2=对内' - int64 upload_bucket = 11; // 上传桶类型 + int64 api_type = 10; // 请求类型:1=对外,2=对内 + int64 upload_bucket = 11; // 上传桶类型:1=持久,2=缓存 string file_key = 12; // 哈希 string source = 13;// 来源 string metadata = 14; // json格式 @@ -64,6 +169,10 @@ message UploadFileBackendFragmentReq { string resource_id = 16; // 资源ID string backup_type = 17; // 资源备份:oss string upload_type = 18; // 上传方式:s3 + + int64 CacheType = 100; // 缓存类型:0=不缓存 1=存储数据库 + int64 user_id = 101; + int64 guest_id = 102; } message UploadFileBackendFragmentRes { string resource_type = 5; @@ -77,12 +186,10 @@ message UploadFileBackendReq { string file_name = 1; // 文件名 bytes file_content = 2; // 文件流 bytes file_header = 3; // 文件头 - int64 user_id = 4; - int64 guest_id = 5; string file_data = 6; // base64 - int64 api_type = 10; // 请求类型:1=对外,2=对内' - int64 upload_bucket = 11; // 上传桶类型 + int64 api_type = 10; // 请求类型:1=对外,2=对内 + int64 upload_bucket = 11; // 上传桶类型:1=持久,2=缓存 string file_key = 12; // 哈希 string source = 13;// 来源 string metadata = 14; // json格式 @@ -90,6 +197,10 @@ message UploadFileBackendReq { string resource_id = 16; // 资源ID string backup_type = 17; // 资源备份:oss string upload_type = 18; // 上传方式:s3 + + int64 CacheType = 100; // 缓存类型:0=不缓存 1=存储数据库 + int64 user_id = 101; + int64 guest_id = 102; } message UploadFileBackendRes{ @@ -100,25 +211,28 @@ message UploadFileBackendRes{ /* 后端上传--文件流--单文件 */ /* 获取资源列表 */ -message GetResourceListReq{ - optional string resource_id = 1; - optional int64 guest_id =2; - optional int64 user_id =3; - optional string resource_type = 4; - optional string resource_url = 5; - optional string version = 6; - optional int64 api_type = 7; - optional string bucket_name = 8; - optional string source = 9; +message ResourceListReq{ + optional ResourceFilter filter=1; optional int64 current_page =101; optional int64 per_page =102; optional string order_by = 103; } +message ResourceListRes{ + repeated basic.ResourceInfo list=1; + basic.Meta meta =2; +} /* 获取资源列表 */ /* 获取资源详情 */ -message GetResourceInfoReq{ +message ResourceInfoReq{ + optional ResourceFilter filter=1; +} +message ResourceInfoRes{ + basic.ResourceInfo info =1; +} + +message ResourceFilter { optional string resource_id = 1; optional int64 guest_id =2; optional int64 user_id =3; @@ -128,5 +242,13 @@ message GetResourceInfoReq{ optional int64 api_type = 7; optional string bucket_name = 8; optional string source = 9; + optional google.protobuf.Struct filters= 10; // 其他过滤条件 + optional ResourceIds resource_ids =11; // 资源ID列表 + optional string metadata = 12; } + +message ResourceIds { + repeated string resource_ids = 1; +} + /* 获取资源详情 */ \ No newline at end of file