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, ",") // 筛选条件 var where []string if p.Args["id"] != nil { where = append(where, fmt.Sprintf("id=%d", p.Args["id"])) } if p.Args["width"] != nil { where = append(where, fmt.Sprintf("width=%d", p.Args["width"])) } if p.Args["height"] != nil { where = append(where, fmt.Sprintf("height=%d", p.Args["height"])) } if p.Args["content"] != nil { where = append(where, fmt.Sprintf("content='%s'", p.Args["content"])) } if p.Args["remark"] != nil { where = append(where, fmt.Sprintf("remark='%s'", p.Args["remark"])) } if p.Args["description"] != nil { where = append(where, fmt.Sprintf("description='%s'", p.Args["description"])) } if p.Args["tags"] != nil { where = append(where, fmt.Sprintf("tags='%s'", p.Args["tags"])) } if p.Args["rank"] != nil { where = append(where, fmt.Sprintf("rank='%s'", p.Args["rank"])) } if p.Args["comment_num"] != nil { where = append(where, fmt.Sprintf("comment_num=%d", p.Args["comment_num"])) } if p.Args["praise_count"] != nil { where = append(where, fmt.Sprintf("praise_count=%d", p.Args["praise_count"])) } if p.Args["collect_count"] != nil { where = append(where, fmt.Sprintf("collect_count=%d", p.Args["collect_count"])) } if p.Args["article_id"] != nil { where = append(where, fmt.Sprintf("article_id=%d", p.Args["article_id"])) } if p.Args["user_id"] != nil { where = append(where, fmt.Sprintf("user_id=%d", p.Args["user_id"])) } if p.Args["create_time"] != nil { where = append(where, fmt.Sprintf("create_time='%s'", p.Args["create_time"])) } if p.Args["update_time"] != nil { where = append(where, fmt.Sprintf("update_time='%s'", p.Args["update_time"])) } 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 []Image 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_id") { // 取到所有的用户ID, 去除重复 user_ids := make(map[int]bool) for _, image := range images { user_ids[image.UserID] = true } // map 转换为数组 uniqueIds := make([]int, 0, len(user_ids)) for id := range user_ids { uniqueIds = append(uniqueIds, id) } // 合并为以逗号分隔的字符串 user_ids_str := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(uniqueIds)), ","), "[]") // 查询用户信息 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 } // 将用户信息与图像信息关联 for i, image := range images { for _, user := range users { if image.UserID == user.ID { images[i].User = user } } } } // 获取文章信息(如果图像列表不为空且请求字段中包含article) if len(images) > 0 && strings.Contains(fields_str, "article_id") { // 取到所有的文章ID, 去除重复 article_ids := make(map[int]bool) for _, image := range images { article_ids[image.ArticleID] = true } // map 转换为数组 uniqueIds := make([]int, 0, len(article_ids)) for id := range article_ids { uniqueIds = append(uniqueIds, id) } // 合并为以逗号分隔的字符串 article_ids_str := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(uniqueIds)), ","), "[]") // 查询文章信息 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 } // 将文章信息与图像信息关联 for i, image := range images { for _, article := range articles { if image.ArticleID == article.ID { images[i].Article = article } } } } return map[string]interface{}{ "list": images, "next": true, }, nil }, }, }})}) if err != nil { return schema, err } return schema, nil }