package api import ( "fmt" "log" "strings" "git.satori.love/gameui/webp/models" "github.com/graphql-go/graphql" "github.com/graphql-go/graphql/language/ast" "github.com/jmoiron/sqlx" ) func NewSchema(config Config) (graphql.Schema, error) { // 打开数据库连接 connection, err := sqlx.Connect("mysql", fmt.Sprintf( "%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", config.Mysql.UserName, config.Mysql.Password, config.Mysql.Host, config.Mysql.Port, config.Mysql.Database, )) if err != nil { log.Fatalln("连接数据库失败", err) } // 文章的可选字段 article := graphql.NewObject(graphql.ObjectConfig{ Name: "Article", Fields: graphql.Fields{ "id": &graphql.Field{Type: graphql.Int}, "title": &graphql.Field{Type: graphql.String}, "tags": &graphql.Field{Type: graphql.String}, "create_time": &graphql.Field{Type: graphql.DateTime}, "update_time": &graphql.Field{Type: graphql.DateTime}, }, }) // 用户的可选字段 user := graphql.NewObject(graphql.ObjectConfig{ Name: "User", Fields: graphql.Fields{ "id": &graphql.Field{Type: graphql.Int}, "user_name": &graphql.Field{Type: graphql.String}, "avatar": &graphql.Field{Type: graphql.String}, "rank": &graphql.Field{Type: graphql.String}, "price": &graphql.Field{Type: graphql.Float}, "create_time": &graphql.Field{Type: graphql.DateTime}, "update_time": &graphql.Field{Type: graphql.DateTime}, }, }) // 图像中的文字提取 [{"text": "角色选择", "confidence": 0.8484202027320862, "coordinate": [[666.0, 66.0], [908.0, 81.0], [903.0, 174.0], [661.0, 160.0]]} text := graphql.NewObject(graphql.ObjectConfig{ Name: "Text", Fields: graphql.Fields{ "text": &graphql.Field{Type: graphql.String}, "confidence": &graphql.Field{Type: graphql.Float}, "coordinate": &graphql.Field{Type: &graphql.List{ OfType: graphql.NewList(graphql.Float), }}, }, }) // 图像的可选字段 image := graphql.NewObject(graphql.ObjectConfig{ Name: "Image", Fields: graphql.Fields{ "id": &graphql.Field{Type: graphql.Int}, "width": &graphql.Field{Type: graphql.Int}, "height": &graphql.Field{Type: graphql.Int}, "content": &graphql.Field{Type: graphql.String}, "remark": &graphql.Field{Type: graphql.String}, "description": &graphql.Field{Type: graphql.String}, "tags": &graphql.Field{Type: graphql.String}, "rank": &graphql.Field{Type: graphql.String}, "text": &graphql.Field{Type: graphql.NewList(text)}, "comment_num": &graphql.Field{Type: graphql.Int}, "article_category_top_id": &graphql.Field{Type: graphql.Int}, "praise_count": &graphql.Field{Type: graphql.Int}, "collect_count": &graphql.Field{Type: graphql.Int}, "create_time": &graphql.Field{Type: graphql.DateTime}, "update_time": &graphql.Field{Type: graphql.DateTime}, "user": &graphql.Field{Type: user}, "article": &graphql.Field{Type: article}, }, }) schema, err := graphql.NewSchema(graphql.SchemaConfig{Query: graphql.NewObject(graphql.ObjectConfig{Name: "RootQuery", Fields: graphql.Fields{ "users": &graphql.Field{ Type: graphql.NewObject(graphql.ObjectConfig{ Name: "UserConnection", Fields: graphql.Fields{ "list": &graphql.Field{Type: graphql.NewList(user)}, "next": &graphql.Field{Type: graphql.String}, "total": &graphql.Field{Type: graphql.Int}, }, }), Args: graphql.FieldConfigArgument{ "id": &graphql.ArgumentConfig{Type: graphql.Int}, "user_name": &graphql.ArgumentConfig{Type: graphql.String}, "avatar": &graphql.ArgumentConfig{Type: graphql.String}, "rank": &graphql.ArgumentConfig{Type: graphql.String}, "create_time": &graphql.ArgumentConfig{Type: graphql.DateTime}, "update_time": &graphql.ArgumentConfig{Type: graphql.DateTime}, "text": &graphql.ArgumentConfig{Type: graphql.String}, // 查找图像中的文字 "first": &graphql.ArgumentConfig{Type: graphql.Int, DefaultValue: 10}, // 翻页参数 "after": &graphql.ArgumentConfig{Type: graphql.String, DefaultValue: "0"}, // 翻页参数 }, Resolve: func(p graphql.ResolveParams) (interface{}, error) { var fields []string requestedFields := p.Info.FieldASTs[0].SelectionSet.Selections for _, field := range requestedFields { fieldAST, ok := field.(*ast.Field) if ok { switch fieldAST.Name.Value { case "list": for _, field := range fieldAST.SelectionSet.Selections { fieldAST, ok := field.(*ast.Field) if ok { fields = append(fields, fieldAST.Name.Value) } } case "next": fmt.Println("next") case "text": fmt.Println("text") default: fmt.Println(fieldAST.Name.Value) } } } first := p.Args["first"] after := p.Args["after"] fields_str := strings.Join(fields, ",") var where []string if p.Args["id"] != nil { where = append(where, fmt.Sprintf("id=%d", p.Args["id"])) } if p.Args["user_name"] != nil { where = append(where, fmt.Sprintf("user_name='%s'", p.Args["user_name"])) } // 筛选条件 where_str := strings.Join(where, " AND ") if where_str != "" { where_str = "WHERE " + where_str } var query strings.Builder query.WriteString(fmt.Sprintf("SELECT %s FROM web_member %s LIMIT %d OFFSET %s", fields_str, where_str, first, after)) // 返回翻页信息 var users []User if err := connection.Select(&users, query.String()); err != nil { fmt.Println("获取用户列表失败", err) return nil, err } return map[string]interface{}{ "list": users, "next": true, }, nil }, }, "images": &graphql.Field{ Type: graphql.NewObject(graphql.ObjectConfig{ Name: "ImageConnection", Fields: graphql.Fields{ "list": &graphql.Field{Type: graphql.NewList(image)}, "next": &graphql.Field{Type: graphql.String}, "total": &graphql.Field{Type: graphql.Int}, }, }), Args: graphql.FieldConfigArgument{ "id": &graphql.ArgumentConfig{Type: graphql.Int}, "width": &graphql.ArgumentConfig{Type: graphql.Int}, "height": &graphql.ArgumentConfig{Type: graphql.Int}, "content": &graphql.ArgumentConfig{Type: graphql.String}, "remark": &graphql.ArgumentConfig{Type: graphql.String}, "description": &graphql.ArgumentConfig{Type: graphql.String}, "tags": &graphql.ArgumentConfig{Type: graphql.String}, "rank": &graphql.ArgumentConfig{Type: graphql.String}, "text": &graphql.ArgumentConfig{Type: graphql.String}, // 查找图像中的文字 "comment_num": &graphql.ArgumentConfig{Type: graphql.Int}, "praise_count": &graphql.ArgumentConfig{Type: graphql.Int}, "collect_count": &graphql.ArgumentConfig{Type: graphql.Int}, "article_id": &graphql.ArgumentConfig{Type: graphql.Int}, "user_id": &graphql.ArgumentConfig{Type: graphql.Int}, "create_time": &graphql.ArgumentConfig{Type: graphql.DateTime}, "update_time": &graphql.ArgumentConfig{Type: graphql.DateTime}, "first": &graphql.ArgumentConfig{Type: graphql.Int, DefaultValue: 10}, // 翻页参数 "after": &graphql.ArgumentConfig{Type: graphql.String, DefaultValue: "0"}, // 翻页参数 }, Resolve: func(p graphql.ResolveParams) (interface{}, error) { // 返回字段 var fields []string requestedFields := p.Info.FieldASTs[0].SelectionSet.Selections for _, field := range requestedFields { fieldAST, ok := field.(*ast.Field) if ok { switch fieldAST.Name.Value { case "list": for _, field := range fieldAST.SelectionSet.Selections { fieldAST, ok := field.(*ast.Field) if ok { switch fieldAST.Name.Value { case "user": fields = append(fields, "user_id") case "article": fields = append(fields, "article_id") default: fields = append(fields, fieldAST.Name.Value) } } } case "next": fmt.Println("next") default: fmt.Println(fieldAST.Name.Value) } } } first := p.Args["first"] after := p.Args["after"] fields_str := strings.Join(fields, ",") // 参数到 SQL 格式字符串的映射 var argToSQLFormat = map[string]string{ "id": "id=%d", "width": "width=%d", "height": "height=%d", "content": "content='%s'", "remark": "remark='%s'", "description": "description='%s'", "tags": "tags='%s'", "rank": "rank='%s'", "comment_num": "comment_num=%d", "praise_count": "praise_count=%d", "collect_count": "collect_count=%d", "article_id": "article_id=%d", "user_id": "user_id=%d", "create_time": "create_time='%s'", "update_time": "update_time='%s'", } // 筛选条件 var where []string for arg, format := range argToSQLFormat { if p.Args[arg] != nil { where = append(where, fmt.Sprintf(format, p.Args[arg])) } } // 特殊处理 text 参数 if p.Args["text"] != nil { id_list := models.ElasticsearchSearch(p.Args["text"].(string)).GetIDList() id_list_str := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(id_list)), ","), "[]") fmt.Println("id_list_str:", id_list_str) if id_list_str == "" { return map[string]interface{}{ "list": []Image{}, "next": false, "total": 0, }, nil } where = append(where, fmt.Sprintf("id IN (%s)", id_list_str)) } where_str := strings.Join(where, " AND ") // 执行查询 var query strings.Builder query.WriteString(fmt.Sprintf("SELECT %s FROM web_images WHERE %s LIMIT %d OFFSET %s", fields_str, where_str, first, after)) var images ImageList if err := connection.Select(&images, query.String()); err != nil { fmt.Println("获取图像列表失败", err) return nil, err } // 获取用户信息(如果图像列表不为空且请求字段中包含user) if len(images) > 0 && strings.Contains(fields_str, "user") { user_ids_str := images.ToAllUserID().ToString() var users []User if err := connection.Select(&users, fmt.Sprintf("SELECT id,user_name,avatar,rank,create_time,update_time FROM web_member WHERE id IN (%s)", user_ids_str)); err != nil { fmt.Println("获取用户列表失败", err) return nil, err } // 将用户信息与图像信息关联 images.SetUser(users) } // 获取文章信息(如果图像列表不为空且请求字段中包含article) if len(images) > 0 && strings.Contains(fields_str, "article") { article_ids_str := images.ToAllArticleID().ToString() var articles []Article if err := connection.Select(&articles, fmt.Sprintf("SELECT id,title,tags,create_time,update_time FROM web_article WHERE id IN (%s)", article_ids_str)); err != nil { fmt.Println("获取文章列表失败", err) return nil, err } // 将文章信息与图像信息关联 images.SetArticle(articles) } return map[string]interface{}{ "list": images, "next": true, }, nil }, }, }})}) if err != nil { return schema, err } return schema, nil }