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" ) var connection *sqlx.DB func init() { var err error user := models.Viper.Get("mysql.user").(string) password := models.Viper.Get("mysql.password").(string) host := models.Viper.Get("mysql.host").(string) port := models.Viper.Get("mysql.port").(int) database := models.Viper.Get("mysql.database").(string) connection, err = sqlx.Connect("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", user, password, host, port, database)) if err != nil { log.Fatalln("连接数据库失败", err) } } func NewSchema() (graphql.Schema, error) { // 文章的可选字段 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}, }, }) 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}, "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}, "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 { if fieldAST.Name.Value == "list" { for _, field := range fieldAST.SelectionSet.Selections { fieldAST, ok := field.(*ast.Field) if ok { //if fieldAST.Name.Value == "avatar" { // fieldAST.Name.Value = fmt.Sprintf("IFNULL(%s,'')", fieldAST.Name.Value) //} fields = append(fields, fieldAST.Name.Value) } } } else if fieldAST.Name.Value == "next" { fmt.Println("next") } else { fields = append(fields, 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)) // 返回翻页信息 fmt.Println(query.String()) var users []User if err := connection.Select(&users, query.String()); err != nil { fmt.Println("获取用户列表失败", err) return nil, err } //return users, nil //var users []User //// 获取用户列表 //if err := connection.Select(&users, "SELECT id,user_name,avatar,rank,create_time,update_time FROM web_member"); err != nil { // fmt.Println("获取用户列表失败", err) // return nil, err //} //// 获取总数 //var count int //if err := connection.Get(&count, "SELECT COUNT(*) FROM web_member"); err != nil { // fmt.Println("获取用户总数失败", err) // return nil, err //} return map[string]interface{}{ "list": users, "next": "2333", }, 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}, "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 { if fieldAST.Name.Value == "list" { for _, field := range fieldAST.SelectionSet.Selections { fieldAST, ok := field.(*ast.Field) if ok { if fieldAST.Name.Value == "user" { fields = append(fields, "user_id") } else if fieldAST.Name.Value == "article" { fields = append(fields, "article_id") } else { fields = append(fields, fieldAST.Name.Value) } } } } else if fieldAST.Name.Value == "next" { fmt.Println("next") } else { fields = append(fields, 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"])) } 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)) fmt.Println(query.String()) 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": "2333", }, nil }, }, }})}) if err != nil { return schema, err } return schema, nil }