分页查询
This commit is contained in:
		
							
								
								
									
										256
									
								
								api/graphql.go
									
									
									
									
									
								
							
							
						
						
									
										256
									
								
								api/graphql.go
									
									
									
									
									
								
							@@ -4,6 +4,7 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"git.satori.love/gameui/webp/models"
 | 
			
		||||
@@ -11,6 +12,7 @@ import (
 | 
			
		||||
	"github.com/graphql-go/graphql/language/ast"
 | 
			
		||||
	"github.com/jmoiron/sqlx"
 | 
			
		||||
	"github.com/mitchellh/mapstructure"
 | 
			
		||||
	"github.com/thoas/go-funk"
 | 
			
		||||
	"gorm.io/driver/mysql"
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
)
 | 
			
		||||
@@ -97,12 +99,13 @@ func NewSchema(config Config) (graphql.Schema, error) {
 | 
			
		||||
		Name:        "Article",
 | 
			
		||||
		Description: "文章",
 | 
			
		||||
		Fields: graphql.Fields{
 | 
			
		||||
			"id":          &graphql.Field{Type: graphql.Int, Description: "文章ID"},
 | 
			
		||||
			"title":       &graphql.Field{Type: graphql.String, Description: "文章标题"},
 | 
			
		||||
			"tags":        &graphql.Field{Type: graphql.String, Description: "文章标签"},
 | 
			
		||||
			"user":        &graphql.Field{Type: user, Description: "文章所属用户"},
 | 
			
		||||
			"create_time": &graphql.Field{Type: graphql.DateTime, Description: "文章创建时间"},
 | 
			
		||||
			"update_time": &graphql.Field{Type: graphql.DateTime, Description: "文章更新时间"},
 | 
			
		||||
			"id":          &graphql.Field{Type: graphql.Int, Description: "ID"},
 | 
			
		||||
			"title":       &graphql.Field{Type: graphql.String, Description: "标题"},
 | 
			
		||||
			"orientation": &graphql.Field{Type: graphql.String, Description: "方向"},
 | 
			
		||||
			"tags":        &graphql.Field{Type: graphql.String, Description: "标签"},
 | 
			
		||||
			"user":        &graphql.Field{Type: user, Description: "所属用户"},
 | 
			
		||||
			"create_time": &graphql.Field{Type: graphql.DateTime, Description: "创建时间"},
 | 
			
		||||
			"update_time": &graphql.Field{Type: graphql.DateTime, Description: "更新时间"},
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
@@ -167,7 +170,6 @@ func NewSchema(config Config) (graphql.Schema, error) {
 | 
			
		||||
					if p.Args["text"] != nil {
 | 
			
		||||
						var texts TextList
 | 
			
		||||
						for _, text := range p.Source.(Image).Text {
 | 
			
		||||
							fmt.Println("san", text.Text)
 | 
			
		||||
							if strings.Contains(text.Text, p.Args["text"].(string)) {
 | 
			
		||||
								texts = append(texts, text)
 | 
			
		||||
							}
 | 
			
		||||
@@ -193,18 +195,6 @@ func NewSchema(config Config) (graphql.Schema, error) {
 | 
			
		||||
				for _, field := range fieldAST.SelectionSet.Selections {
 | 
			
		||||
					fieldAST, ok := field.(*ast.Field)
 | 
			
		||||
					if ok {
 | 
			
		||||
						if fieldAST.Name.Value == "user" {
 | 
			
		||||
							fields = append(fields, "user_id")
 | 
			
		||||
							continue
 | 
			
		||||
						}
 | 
			
		||||
						if fieldAST.Name.Value == "article" {
 | 
			
		||||
							fields = append(fields, "article_id")
 | 
			
		||||
							continue
 | 
			
		||||
						}
 | 
			
		||||
						if fieldAST.Name.Value == "similars" {
 | 
			
		||||
							// 跳过自定义字段
 | 
			
		||||
							continue
 | 
			
		||||
						}
 | 
			
		||||
						fields = append(fields, fieldAST.Name.Value)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
@@ -344,7 +334,7 @@ func NewSchema(config Config) (graphql.Schema, error) {
 | 
			
		||||
				},
 | 
			
		||||
			}),
 | 
			
		||||
			Args: graphql.FieldConfigArgument{
 | 
			
		||||
				"preference":    &graphql.ArgumentConfig{Type: graphql.String, Description: "使用浏览记录获取的偏好推荐图像"},
 | 
			
		||||
				"interest":      &graphql.ArgumentConfig{Type: graphql.Int, Description: "获取指定ID用户的兴趣推荐图像"},
 | 
			
		||||
				"similar":       &graphql.ArgumentConfig{Type: graphql.Int, Description: "获取与指定ID图像相似的图像"},
 | 
			
		||||
				"id":            &graphql.ArgumentConfig{Type: graphql.Int, Description: "获取指定ID的图像"},
 | 
			
		||||
				"width":         &graphql.ArgumentConfig{Type: graphql.Int, Description: "筛选图像中指定宽度的"},
 | 
			
		||||
@@ -364,72 +354,49 @@ func NewSchema(config Config) (graphql.Schema, error) {
 | 
			
		||||
				"update_time":   &graphql.ArgumentConfig{Type: graphql.DateTime, Description: "筛选图像中更新时间等于指定值的"},
 | 
			
		||||
				"first":         &graphql.ArgumentConfig{Type: graphql.Int, Description: "翻页参数(傳回清單中的前n個元素)"},
 | 
			
		||||
				"last":          &graphql.ArgumentConfig{Type: graphql.Int, Description: "翻页参数(傳回清單中的最後n個元素)"},
 | 
			
		||||
				"after":         &graphql.ArgumentConfig{Type: graphql.String, Description: "翻页参数(傳回清單中指定遊標之後的元素)"},
 | 
			
		||||
				"before":        &graphql.ArgumentConfig{Type: graphql.String, Description: "翻页参数(傳回清單中指定遊標之前的元素)"},
 | 
			
		||||
				"after":         &graphql.ArgumentConfig{Type: graphql.Int, Description: "翻页参数(傳回清單中指定遊標之後的元素)"},
 | 
			
		||||
				"before":        &graphql.ArgumentConfig{Type: graphql.Int, Description: "翻页参数(傳回清單中指定遊標之前的元素)"},
 | 
			
		||||
			},
 | 
			
		||||
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
 | 
			
		||||
				// 定义参数结构体
 | 
			
		||||
				var args struct {
 | 
			
		||||
					First      int
 | 
			
		||||
					Last       int
 | 
			
		||||
					After      string
 | 
			
		||||
					Before     string
 | 
			
		||||
					Text       string
 | 
			
		||||
					Preference string
 | 
			
		||||
					Similar    int
 | 
			
		||||
					First    int
 | 
			
		||||
					Last     int
 | 
			
		||||
					After    int
 | 
			
		||||
					Before   int
 | 
			
		||||
					Text     string
 | 
			
		||||
					Interest int
 | 
			
		||||
					Similar  int
 | 
			
		||||
				}
 | 
			
		||||
				mapstructure.Decode(p.Args, &args)
 | 
			
		||||
 | 
			
		||||
				// 参数到 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 limit = 10
 | 
			
		||||
				if args.First != 0 {
 | 
			
		||||
					limit = args.First
 | 
			
		||||
				} else if args.Last != 0 {
 | 
			
		||||
					limit = args.Last
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				var total int
 | 
			
		||||
				var images []Image
 | 
			
		||||
				var fields = get_fields(p.Info.FieldASTs[0].SelectionSet.Selections)
 | 
			
		||||
				var query = db.Limit(limit)
 | 
			
		||||
 | 
			
		||||
				// 参数映射
 | 
			
		||||
				var argFormat = []string{"id", "width", "height", "content", "remark", "description", "tags", "rank", "comment_num", "praise_count", "collect_count", "article_id", "user_id", "create_time", "update_time"}
 | 
			
		||||
 | 
			
		||||
				// 筛选条件
 | 
			
		||||
				var where []string
 | 
			
		||||
				var order []string
 | 
			
		||||
				for arg, format := range argToSQLFormat {
 | 
			
		||||
					if p.Args[arg] != nil {
 | 
			
		||||
						where = append(where, fmt.Sprintf(format, p.Args[arg]))
 | 
			
		||||
				for _, format := range argFormat {
 | 
			
		||||
					if p.Args[format] != nil {
 | 
			
		||||
						query = query.Where(fmt.Sprintf(format, " = ?"), p.Args[format])
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				var id_list []string
 | 
			
		||||
				var list []int
 | 
			
		||||
				var id_list [][]int
 | 
			
		||||
 | 
			
		||||
				// 特殊处理 preference 参数
 | 
			
		||||
				if args.Preference != "" {
 | 
			
		||||
					// 去除空格并拆分以逗号分割的ID
 | 
			
		||||
					id_list = strings.Split(strings.ReplaceAll(args.Preference, " ", ""), ",")
 | 
			
		||||
					// 使用这一组 id 推荐
 | 
			
		||||
					fmt.Println("preference:", args.Preference)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// 特殊处理 similar 参数
 | 
			
		||||
				if args.Similar != 0 {
 | 
			
		||||
					id_list := models.GetSimilarImagesIdList(args.Similar, 200)
 | 
			
		||||
					ids_str := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(id_list)), ","), "[]")
 | 
			
		||||
					if ids_str == "" {
 | 
			
		||||
						return map[string]interface{}{"list": []Image{}, "total": 0}, nil
 | 
			
		||||
					}
 | 
			
		||||
					where = append(where, fmt.Sprintf("id IN (%s)", ids_str))
 | 
			
		||||
					order = append(order, fmt.Sprintf("ORDER BY FIELD(id,%s)", ids_str))
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// 特殊处理 text 参数
 | 
			
		||||
				// 筛选:提取文字
 | 
			
		||||
				if args.Text != "" {
 | 
			
		||||
					resp, err := models.ZincSearch(map[string]interface{}{
 | 
			
		||||
						"query": map[string]interface{}{
 | 
			
		||||
@@ -447,84 +414,123 @@ func NewSchema(config Config) (graphql.Schema, error) {
 | 
			
		||||
						"from": 0,
 | 
			
		||||
						"size": 200,
 | 
			
		||||
					})
 | 
			
		||||
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						fmt.Println("ZincSearch 获取图像列表失败", err)
 | 
			
		||||
						return nil, err
 | 
			
		||||
					}
 | 
			
		||||
					id_list = resp.ToIDList(args.First, args.Last, args.After, args.Before)
 | 
			
		||||
					id_list_str := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(id_list)), ","), "[]")
 | 
			
		||||
					if id_list_str == "" {
 | 
			
		||||
						return map[string]interface{}{
 | 
			
		||||
							"list":  []Image{},
 | 
			
		||||
							"total": 0,
 | 
			
		||||
						}, nil
 | 
			
		||||
 | 
			
		||||
					var item []int
 | 
			
		||||
 | 
			
		||||
					for _, hit := range resp.Hits.Hits {
 | 
			
		||||
						num, _ := strconv.Atoi(hit.ID)
 | 
			
		||||
						item = append(item, num)
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					id_list = append(id_list, item)
 | 
			
		||||
 | 
			
		||||
					if len(id_list) == 0 {
 | 
			
		||||
						return map[string]interface{}{"list": []Image{}, "total": 0}, nil
 | 
			
		||||
					}
 | 
			
		||||
					where = append(where, fmt.Sprintf("id IN (%s)", id_list_str))
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				where_str := strings.Join(where, " AND ")
 | 
			
		||||
				order_str := strings.Join(order, "")
 | 
			
		||||
				// 筛选:相似图像
 | 
			
		||||
				if args.Similar != 0 {
 | 
			
		||||
					var item []int
 | 
			
		||||
					for _, id := range models.GetSimilarImagesIdList(args.Similar, 200) {
 | 
			
		||||
						item = append(item, int(id))
 | 
			
		||||
					}
 | 
			
		||||
					id_list = append(id_list, item)
 | 
			
		||||
 | 
			
		||||
				if where_str != "" {
 | 
			
		||||
					where_str = "WHERE " + where_str
 | 
			
		||||
					if len(id_list) == 0 {
 | 
			
		||||
						return map[string]interface{}{"list": []Image{}, "total": 0}, nil
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// 处理翻页参数
 | 
			
		||||
				var limit, offset int
 | 
			
		||||
				if args.First == 0 && args.Last == 0 {
 | 
			
		||||
					limit = 10
 | 
			
		||||
					offset = 0
 | 
			
		||||
				// 筛选:兴趣推荐
 | 
			
		||||
				if args.Interest != 0 {
 | 
			
		||||
					fmt.Println("Interest:", args.Interest)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// 排序
 | 
			
		||||
 | 
			
		||||
				// 截取:取交集
 | 
			
		||||
				if len(id_list) != 0 {
 | 
			
		||||
					list = id_list[0]
 | 
			
		||||
					if len(id_list) > 1 {
 | 
			
		||||
						for _, slice := range id_list[1:] {
 | 
			
		||||
							list = funk.Join(list, slice, funk.InnerJoin).([]int)
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					if len(list) == 0 {
 | 
			
		||||
						return map[string]interface{}{"list": []Image{}, "total": 0}, nil
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				total = len(list)
 | 
			
		||||
 | 
			
		||||
				// 截取: 分页
 | 
			
		||||
				if args.After != 0 {
 | 
			
		||||
					index := -1
 | 
			
		||||
					for i, id := range list {
 | 
			
		||||
						if id == args.After {
 | 
			
		||||
							index = i
 | 
			
		||||
							break
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					if index != -1 {
 | 
			
		||||
						list = list[index+1:]
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if args.Before != 0 {
 | 
			
		||||
					index := -1
 | 
			
		||||
					for i, id := range list {
 | 
			
		||||
						if id == args.Before {
 | 
			
		||||
							index = i
 | 
			
		||||
							break
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					if index != -1 {
 | 
			
		||||
						list = list[:index]
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if args.First != 0 {
 | 
			
		||||
					limit = args.First
 | 
			
		||||
					offset = 0
 | 
			
		||||
					list = list[:args.First]
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if args.Last != 0 {
 | 
			
		||||
					limit = args.Last
 | 
			
		||||
					offset = len(id_list) - limit
 | 
			
		||||
					list = list[len(list)-args.Last:]
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// 执行查询
 | 
			
		||||
				var query strings.Builder
 | 
			
		||||
				fields := strings.Join(get_fields(p.Info.FieldASTs[0].SelectionSet.Selections), ",")
 | 
			
		||||
				query.WriteString(fmt.Sprintf("SELECT %s FROM web_images %s %s LIMIT %d OFFSET %d", fields, where_str, order_str, limit, offset))
 | 
			
		||||
				if args.First == 0 && args.Last == 0 {
 | 
			
		||||
					list = list[:10]
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				var images ImageList
 | 
			
		||||
				var q = query.String()
 | 
			
		||||
				if err := connection.Select(&images, q); err != nil {
 | 
			
		||||
				// 存在外部筛选条件
 | 
			
		||||
				if len(id_list) > 0 && len(list) > 0 {
 | 
			
		||||
					query = query.Where("id IN ?", list)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// 输出
 | 
			
		||||
				if funk.Contains(fields, "user") {
 | 
			
		||||
					query = query.Preload("User")
 | 
			
		||||
					fmt.Println("加载 user")
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if funk.Contains(fields, "article") {
 | 
			
		||||
					query = query.Preload("Article")
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if err := query.Find(&images).Error; err != nil {
 | 
			
		||||
					fmt.Println("获取图像列表失败", err)
 | 
			
		||||
					return nil, err
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// 获取用户信息(如果图像列表不为空且请求字段中包含user)
 | 
			
		||||
				if len(images) > 0 && strings.Contains(fields, "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, "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,
 | 
			
		||||
					"total": 0,
 | 
			
		||||
					"total": total,
 | 
			
		||||
				}, nil
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
 
 | 
			
		||||
@@ -55,30 +55,8 @@ func (images *ImageList) ToAllUserID() (uniqueIds IDS) {
 | 
			
		||||
	return uniqueIds
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 为每个图像设置用户信息
 | 
			
		||||
func (images *ImageList) SetUser(userList []User) {
 | 
			
		||||
	for i, image := range *images {
 | 
			
		||||
		for _, user := range userList {
 | 
			
		||||
			if image.UserID == user.ID {
 | 
			
		||||
				(*images)[i].User = user
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 为每个图像设置文章信息
 | 
			
		||||
func (images *ImageList) SetArticle(articleList []Article) {
 | 
			
		||||
	for i, image := range *images {
 | 
			
		||||
		for _, article := range articleList {
 | 
			
		||||
			if image.ArticleID == article.ID {
 | 
			
		||||
				(*images)[i].Article = article
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Image struct {
 | 
			
		||||
	ID           int       `json:"id"            db:"id"`
 | 
			
		||||
	ID           int       `json:"id"            db:"id" gorm:"primaryKey"`
 | 
			
		||||
	Width        int       `json:"width"         db:"width"`
 | 
			
		||||
	Height       int       `json:"height"        db:"height"`
 | 
			
		||||
	Content      string    `json:"content"       db:"content"`
 | 
			
		||||
@@ -93,9 +71,13 @@ type Image struct {
 | 
			
		||||
	UserID       int       `json:"user_id"       db:"user_id"`
 | 
			
		||||
	CreateTime   time.Time `json:"create_time"   db:"create_time"`
 | 
			
		||||
	UpdateTime   time.Time `json:"update_time"   db:"update_time"`
 | 
			
		||||
	Text         TextList  `json:"text"          db:"text"`
 | 
			
		||||
	User         User      `json:"user"          db:"-"`
 | 
			
		||||
	Article      Article   `json:"article"       db:"-"`
 | 
			
		||||
	Text         TextList  `json:"text"          db:"text" gorm:"type:json"`
 | 
			
		||||
	User         User      `json:"user"          gorm:"foreignKey:UserID"`
 | 
			
		||||
	Article      Article   `json:"article"       gorm:"foreignKey:ArticleID"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (Image) TableName() string {
 | 
			
		||||
	return "web_images"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type TextList []struct {
 | 
			
		||||
@@ -109,7 +91,7 @@ func (a *TextList) Scan(value interface{}) error {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type User struct {
 | 
			
		||||
	ID         int       `json:"id"          db:"id"`
 | 
			
		||||
	ID         int       `json:"id"          db:"id" gorm:"primaryKey"`
 | 
			
		||||
	UserName   *string   `json:"user_name"   db:"user_name"`
 | 
			
		||||
	Avatar     *string   `json:"avatar"      db:"avatar"`
 | 
			
		||||
	Rank       *string   `json:"rank"        db:"rank"`
 | 
			
		||||
@@ -117,12 +99,21 @@ type User struct {
 | 
			
		||||
	UpdateTime time.Time `json:"update_time" db:"update_time"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (User) TableName() string {
 | 
			
		||||
	return "web_member"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Article struct {
 | 
			
		||||
	ID         int       `json:"id"          db:"id"`
 | 
			
		||||
	Title      string    `json:"title"       db:"title"`
 | 
			
		||||
	Tags       string    `json:"tags"        db:"tags"`
 | 
			
		||||
	CreateTime time.Time `json:"create_time" db:"create_time"`
 | 
			
		||||
	UpdateTime time.Time `json:"update_time" db:"update_time"`
 | 
			
		||||
	ID          int       `json:"id"          db:"id" gorm:"primaryKey"`
 | 
			
		||||
	Title       string    `json:"title"       db:"title"`
 | 
			
		||||
	Orientation string    `json:"orientation" db:"orientation"`
 | 
			
		||||
	Tags        string    `json:"tags"        db:"tags"`
 | 
			
		||||
	CreateTime  time.Time `json:"create_time" db:"create_time"`
 | 
			
		||||
	UpdateTime  time.Time `json:"update_time" db:"update_time"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (Article) TableName() string {
 | 
			
		||||
	return "web_article"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Category struct {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user