From dfd2fd939218dab9a6c2b0e290cf4a1a5bfa9916 Mon Sep 17 00:00:00 2001 From: yystopf Date: Sat, 12 Feb 2022 17:13:26 +0800 Subject: [PATCH] add: person module --- docs/docs.go | 221 +++++++++++++++++++++++ docs/swagger.json | 221 +++++++++++++++++++++++ docs/swagger.yaml | 147 +++++++++++++++ internal/controller/api/person.go | 201 +++++++++++++++++++++ internal/dao/person.go | 79 ++++++++ internal/model/person.go | 61 +++++++ internal/service/person.go | 59 ++++++ migrations/000002_create_people.down.sql | 1 + migrations/000002_create_people.up.sql | 11 ++ 9 files changed, 1001 insertions(+) create mode 100644 internal/controller/api/person.go create mode 100644 internal/dao/person.go create mode 100644 internal/model/person.go create mode 100644 internal/service/person.go create mode 100644 migrations/000002_create_people.down.sql create mode 100644 migrations/000002_create_people.up.sql diff --git a/docs/docs.go b/docs/docs.go index cad3e5e..829b79c 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -24,6 +24,201 @@ var doc = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/people": { + "get": { + "description": "此接口用来获取人员数据列表,支持名称模糊查询,以及自定义排序(name, created_at)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "peple" + ], + "summary": "人员列表", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页数量", + "name": "page_size", + "in": "query" + }, + { + "maxLength": 100, + "type": "string", + "description": "名称", + "name": "name", + "in": "query" + }, + { + "type": "string", + "description": "排序字段", + "name": "sort_by", + "in": "query" + }, + { + "type": "string", + "description": "排序类型", + "name": "sort_direction", + "in": "query" + } + ], + "responses": { + "200": { + "description": "请求成功", + "schema": { + "$ref": "#/definitions/model.Person" + } + } + } + }, + "post": { + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "people" + ], + "summary": "新增一条人员数据", + "parameters": [ + { + "maxLength": 100, + "minLength": 1, + "type": "string", + "description": "名称", + "name": "name", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "个性签名", + "name": "signature", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "请求成功", + "schema": { + "$ref": "#/definitions/model.Person" + } + } + } + } + }, + "/people/{id}": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "people" + ], + "summary": "获取单个人员", + "parameters": [ + { + "type": "integer", + "description": "ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "请求成功", + "schema": { + "$ref": "#/definitions/model.Person" + } + } + } + }, + "delete": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "people" + ], + "summary": "删除一条人员数据", + "parameters": [ + { + "type": "integer", + "description": "ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "请求成功", + "schema": { + "$ref": "#/definitions/model.Person" + } + } + } + }, + "patch": { + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "people" + ], + "summary": "修改人员数据", + "parameters": [ + { + "type": "integer", + "description": "ID", + "name": "id", + "in": "path", + "required": true + }, + { + "maxLength": 100, + "type": "string", + "description": "名称", + "name": "name", + "in": "formData" + }, + { + "type": "string", + "description": "个性签名", + "name": "signature", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "请求成功", + "schema": { + "$ref": "#/definitions/model.Person" + } + } + } + } + }, "/templates": { "get": { "description": "一段描述", @@ -229,6 +424,32 @@ var doc = `{ } }, "definitions": { + "model.Person": { + "type": "object", + "properties": { + "created_at": { + "type": "string" + }, + "followed_count": { + "description": "关注数", + "type": "integer" + }, + "id": { + "type": "integer" + }, + "name": { + "description": "名称", + "type": "string" + }, + "signature": { + "description": "个性签名", + "type": "string" + }, + "updated_at": { + "type": "string" + } + } + }, "model.Template": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index f662363..c678a2a 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -8,6 +8,201 @@ }, "basePath": "/api", "paths": { + "/people": { + "get": { + "description": "此接口用来获取人员数据列表,支持名称模糊查询,以及自定义排序(name, created_at)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "peple" + ], + "summary": "人员列表", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页数量", + "name": "page_size", + "in": "query" + }, + { + "maxLength": 100, + "type": "string", + "description": "名称", + "name": "name", + "in": "query" + }, + { + "type": "string", + "description": "排序字段", + "name": "sort_by", + "in": "query" + }, + { + "type": "string", + "description": "排序类型", + "name": "sort_direction", + "in": "query" + } + ], + "responses": { + "200": { + "description": "请求成功", + "schema": { + "$ref": "#/definitions/model.Person" + } + } + } + }, + "post": { + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "people" + ], + "summary": "新增一条人员数据", + "parameters": [ + { + "maxLength": 100, + "minLength": 1, + "type": "string", + "description": "名称", + "name": "name", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "个性签名", + "name": "signature", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "请求成功", + "schema": { + "$ref": "#/definitions/model.Person" + } + } + } + } + }, + "/people/{id}": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "people" + ], + "summary": "获取单个人员", + "parameters": [ + { + "type": "integer", + "description": "ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "请求成功", + "schema": { + "$ref": "#/definitions/model.Person" + } + } + } + }, + "delete": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "people" + ], + "summary": "删除一条人员数据", + "parameters": [ + { + "type": "integer", + "description": "ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "请求成功", + "schema": { + "$ref": "#/definitions/model.Person" + } + } + } + }, + "patch": { + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "people" + ], + "summary": "修改人员数据", + "parameters": [ + { + "type": "integer", + "description": "ID", + "name": "id", + "in": "path", + "required": true + }, + { + "maxLength": 100, + "type": "string", + "description": "名称", + "name": "name", + "in": "formData" + }, + { + "type": "string", + "description": "个性签名", + "name": "signature", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "请求成功", + "schema": { + "$ref": "#/definitions/model.Person" + } + } + } + } + }, "/templates": { "get": { "description": "一段描述", @@ -213,6 +408,32 @@ } }, "definitions": { + "model.Person": { + "type": "object", + "properties": { + "created_at": { + "type": "string" + }, + "followed_count": { + "description": "关注数", + "type": "integer" + }, + "id": { + "type": "integer" + }, + "name": { + "description": "名称", + "type": "string" + }, + "signature": { + "description": "个性签名", + "type": "string" + }, + "updated_at": { + "type": "string" + } + } + }, "model.Template": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 96be62d..994c8ba 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1,5 +1,23 @@ basePath: /api definitions: + model.Person: + properties: + created_at: + type: string + followed_count: + description: 关注数 + type: integer + id: + type: integer + name: + description: 名称 + type: string + signature: + description: 个性签名 + type: string + updated_at: + type: string + type: object model.Template: properties: created_at: @@ -19,6 +37,135 @@ info: title: ShareKnowledgeServer Api version: "1.0" paths: + /people: + get: + consumes: + - application/json + description: 此接口用来获取人员数据列表,支持名称模糊查询,以及自定义排序(name, created_at) + parameters: + - description: 页码 + in: query + name: page + type: integer + - description: 每页数量 + in: query + name: page_size + type: integer + - description: 名称 + in: query + maxLength: 100 + name: name + type: string + - description: 排序字段 + in: query + name: sort_by + type: string + - description: 排序类型 + in: query + name: sort_direction + type: string + produces: + - application/json + responses: + "200": + description: 请求成功 + schema: + $ref: '#/definitions/model.Person' + summary: 人员列表 + tags: + - peple + post: + consumes: + - multipart/form-data + parameters: + - description: 名称 + in: formData + maxLength: 100 + minLength: 1 + name: name + required: true + type: string + - description: 个性签名 + in: formData + name: signature + type: string + produces: + - application/json + responses: + "200": + description: 请求成功 + schema: + $ref: '#/definitions/model.Person' + summary: 新增一条人员数据 + tags: + - people + /people/{id}: + delete: + consumes: + - application/json + parameters: + - description: ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: 请求成功 + schema: + $ref: '#/definitions/model.Person' + summary: 删除一条人员数据 + tags: + - people + get: + consumes: + - application/json + parameters: + - description: ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: 请求成功 + schema: + $ref: '#/definitions/model.Person' + summary: 获取单个人员 + tags: + - people + patch: + consumes: + - multipart/form-data + parameters: + - description: ID + in: path + name: id + required: true + type: integer + - description: 名称 + in: formData + maxLength: 100 + name: name + type: string + - description: 个性签名 + in: formData + name: signature + type: string + produces: + - application/json + responses: + "200": + description: 请求成功 + schema: + $ref: '#/definitions/model.Person' + summary: 修改人员数据 + tags: + - people /templates: get: consumes: diff --git a/internal/controller/api/person.go b/internal/controller/api/person.go new file mode 100644 index 0000000..356aa9a --- /dev/null +++ b/internal/controller/api/person.go @@ -0,0 +1,201 @@ +package api + +import ( + "github.com/gin-gonic/gin" + "github.com/jinzhu/gorm" + "github.com/viletyy/yolk/convert" + "gitlink.org.cn/Gitlink/share-knowledge-server/global" + "gitlink.org.cn/Gitlink/share-knowledge-server/internal/service" + "gitlink.org.cn/Gitlink/share-knowledge-server/pkg/app" + "gitlink.org.cn/Gitlink/share-knowledge-server/pkg/errcode" +) + +type Person struct { + *Base +} + +func NewPerson(base *Base) Person { + return Person{Base: base} +} + +// @Summary 人员列表 +// @Tags peple +// @Description 此接口用来获取人员数据列表,支持名称模糊查询,以及自定义排序(name, created_at) +// @Accept json +// @Produce json +// @Param page query int false "页码" +// @Param page_size query int false "每页数量" +// @Param name query string false "名称" maxlength(100) +// @Param sort_by query string false "排序字段" +// @Param sort_direction query string false "排序类型" +// @Success 200 {object} model.Person "请求成功" +// @Router /people [get] +func (person Person) List(c *gin.Context) { + param := service.GetPersonListRequest{} + response := app.NewResponse(c) + valid, errs := app.BindAndValid(c, ¶m) + if !valid { + global.GO_LOG.Sugar().Errorf("app.BindAndValid errs: %v", errs) + response.ToResponseErrors(errs.Error()) + return + } + + svc := service.New(c.Request.Context()) + pager := app.Pager{Page: app.GetPage(c), PageSize: app.GetPageSize(c)} + total, err := svc.CountPerson(&service.CountPersonRequest{Name: param.Name}) + if err != nil { + global.GO_LOG.Sugar().Errorf("svc.CountPerson err: %v", err) + response.ToErrorResponse(errcode.ErrorCountFail) + return + } + templates, err := svc.GetPersonList(¶m, &pager) + if err != nil { + global.GO_LOG.Sugar().Errorf("svc.GetPersonList err: %v", err) + response.ToErrorResponse(errcode.ErrorGetListFail) + return + } + + response.ToResponseList(templates, total) +} + +// @Summary 获取单个人员 +// @Tags people +// @Description +// @Accept json +// @Produce json +// @Param id path int true "ID" +// @Success 200 {object} model.Person "请求成功" +// @Router /people/{id} [get] +func (person Person) Get(c *gin.Context) { + personID, err := convert.StrTo(c.Param("id")).Int64() + response := app.NewResponse(c) + if err != nil { + global.GO_LOG.Sugar().Errorf("convert.StrTo err: %v", err) + response.ToErrorResponse(errcode.InvalidParams) + return + } + param := service.GetPersonRequest{ID: personID} + valid, errs := app.BindAndValid(c, ¶m) + if !valid { + global.GO_LOG.Sugar().Errorf("app.BindAndValid errs: %v", errs) + response.ToResponseErrors(errs.Errors()) + return + } + + svc := service.New(c.Request.Context()) + dbPerson, err := svc.GetPerson(¶m) + if err != nil { + global.GO_LOG.Sugar().Errorf("svc.GetTemplate err: %v", err) + response.ToErrorResponse(errcode.ErrorGetFail) + return + } + + response.ToResponse(dbPerson) +} + +// @Summary 新增一条人员数据 +// @Tags people +// @Description +// @Accept mpfd +// @Produce json +// @Param name formData string true "名称" minlength(1) maxlength(100) +// @Param signature formData string false "个性签名" +// @Success 200 {object} model.Person "请求成功" +// @Router /people [post] +func (person Person) Create(c *gin.Context) { + param := service.CreatePersonRequest{} + response := app.NewResponse(c) + valid, errs := app.BindAndValid(c, ¶m) + if !valid { + global.GO_LOG.Sugar().Errorf("app.BindAndValid errs: %v", errs) + response.ToResponseErrors(errs.Errors()) + return + } + + svc := service.New(c.Request.Context()) + dbPerson, err := svc.CreatePerson(¶m) + if err != nil { + global.GO_LOG.Sugar().Errorf("svc.CreatePerson err: %v", err) + response.ToErrorResponse(errcode.ErrorCreateFail) + return + } + + response.ToResponse(dbPerson) +} + +// @Summary 修改人员数据 +// @Tags people +// @Description +// @Accept mpfd +// @Produce json +// @Param id path int true "ID" +// @Param name formData string false "名称" maxlength(100) +// @Param signature formData string false "个性签名" +// @Success 200 {object} model.Person "请求成功" +// @Router /people/{id} [patch] +func (person Person) Update(c *gin.Context) { + personID, err := convert.StrTo(c.Param("id")).Int64() + response := app.NewResponse(c) + if err != nil { + global.GO_LOG.Sugar().Errorf("convert.StrTo err: %v", err) + response.ToErrorResponse(errcode.InvalidParams) + return + } + param := service.UpdatePersonRequest{ID: personID} + valid, errs := app.BindAndValid(c, ¶m) + if !valid { + global.GO_LOG.Sugar().Errorf("app.BindAndValid errs: %v", errs) + response.ToResponseErrors(errs) + return + } + svc := service.New(c.Request.Context()) + dbPerson, err := svc.UpdatePerson(¶m) + if err != nil { + if err == gorm.ErrRecordNotFound { + global.GO_LOG.Sugar().Errorf("svc.UpdatePerson err: %v", err) + response.ToErrorResponse(errcode.ErrorGetFail) + return + } else { + global.GO_LOG.Sugar().Errorf("svc.UpdatePerson err: %v", err) + response.ToErrorResponse(errcode.ErrorUpdateFail) + return + } + } + + response.ToResponse(dbPerson) +} + +// @Summary 删除一条人员数据 +// @Tags people +// @Description +// @Accept json +// @Produce json +// @Param id path int true "ID" +// @Success 200 {object} model.Person "请求成功" +// @Router /people/{id} [delete] +func (person Person) Delete(c *gin.Context) { + personID, err := convert.StrTo(c.Param("id")).Int64() + response := app.NewResponse(c) + if err != nil { + global.GO_LOG.Sugar().Errorf("convert.StrTo err: %v", err) + response.ToErrorResponse(errcode.InvalidParams) + return + } + param := service.DeletePersonRequest{ID: personID} + svc := service.New(c.Request.Context()) + dbPerson, err := svc.DeletePerson(¶m) + if err != nil { + if err == gorm.ErrRecordNotFound { + global.GO_LOG.Sugar().Errorf("svc.DeletePerson err: %v", err) + response.ToErrorResponse(errcode.ErrorGetFail) + return + } else { + global.GO_LOG.Sugar().Errorf("svc.DeletePerson err: %v", err) + response.ToErrorResponse(errcode.ErrorDeleteFail) + return + } + } + + errcode.Success.Data = dbPerson + response.ToErrorResponse(errcode.Success) +} diff --git a/internal/dao/person.go b/internal/dao/person.go new file mode 100644 index 0000000..4eb2a0d --- /dev/null +++ b/internal/dao/person.go @@ -0,0 +1,79 @@ +package dao + +import ( + "gitlink.org.cn/Gitlink/share-knowledge-server/internal/model" + "gitlink.org.cn/Gitlink/share-knowledge-server/pkg/app" +) + +func (d *Dao) CountPerson(name string) (int, error) { + person := model.Person{Name: name} + return person.Count(d.Engine) +} + +func (d *Dao) GetPersonList(name string, page, pageSize int, sortBy, sortDirection string) ([]model.Person, error) { + person := model.Person{Name: name} + pageOffset := app.GetPageOffset(page, pageSize) + return person.List(d.Engine, pageOffset, pageSize, sortBy, sortDirection) +} + +func (d *Dao) GetPerson(id int64) (model.Person, error) { + person := model.Person{ + Model: &model.Model{ID: id}, + } + + return person.Get(d.Engine) +} + +func (d *Dao) CreatePerson(name, signature string) (model.Person, error) { + person := model.Person{ + Name: name, + Signature: signature, + } + + return person, person.Create(d.Engine) +} + +func (d *Dao) UpdatePerson(id int64, name, signature string) (model.Person, error) { + person := model.Person{ + Name: name, + Signature: signature, + Model: &model.Model{ID: id}, + } + + dbPerson, err := person.Get(d.Engine) + + if err != nil { + return person, err + } + + return dbPerson, dbPerson.Update(d.Engine) +} + +func (d *Dao) UpdatePersonFollowedCount(id int64, followed_count int) (model.Person, error) { + person := model.Person{ + FollowedCount: followed_count, + Model: &model.Model{ID: id}, + } + + dbPerson, err := person.Get(d.Engine) + + if err != nil { + return person, err + } + + return dbPerson, dbPerson.Update(d.Engine) +} + +func (d *Dao) DeletePerson(id int64) (model.Person, error) { + person := model.Person{ + Model: &model.Model{ID: id}, + } + + dbPerson, err := person.Get(d.Engine) + + if err != nil { + return person, err + } + + return dbPerson, dbPerson.Delete(d.Engine) +} diff --git a/internal/model/person.go b/internal/model/person.go new file mode 100644 index 0000000..cdf3407 --- /dev/null +++ b/internal/model/person.go @@ -0,0 +1,61 @@ +package model + +import ( + "fmt" + + "github.com/jinzhu/gorm" +) + +type Person struct { + *Model + Name string `json:"name"` // 名称 + Signature string `json:"signature"` // 个性签名 + FollowedCount int `json:"followed_count"` // 关注数 +} + +func (p Person) Count(db *gorm.DB) (int, error) { + var count int + if p.Name != "" { + db = db.Where("name = ?", p.Name) + } + if err := db.Model(&p).Count(&count).Error; err != nil { + return 0, err + } + return count, nil +} + +func (p Person) List(db *gorm.DB, pageOffset, pageSize int, sortBy, sortDirection string) (people []Person, err error) { + if pageOffset >= 0 && pageSize > 0 { + db = db.Offset(pageOffset).Limit(pageSize) + } + if p.Name != "" { + db = db.Where("name = ?", p.Name) + } + if sortBy != "" && sortDirection != "" { + db = db.Order(fmt.Sprintf("%s %s", sortBy, sortDirection)) + } + if err = db.Find(&people).Error; err != nil { + return nil, err + } + return +} + +func (p Person) Get(db *gorm.DB) (person Person, err error) { + if notFound := db.Where("id = ?", p.ID).First(&person).RecordNotFound(); notFound { + return p, gorm.ErrRecordNotFound + } + + return person, nil +} + +func (p *Person) Create(db *gorm.DB) error { + return db.Create(p).Error +} + +func (p *Person) Update(db *gorm.DB) error { + return db.Update(p).Error +} + +func (p *Person) Delete(db *gorm.DB) error { + return db.Delete(p).Error +} diff --git a/internal/service/person.go b/internal/service/person.go new file mode 100644 index 0000000..600f699 --- /dev/null +++ b/internal/service/person.go @@ -0,0 +1,59 @@ +package service + +import ( + "gitlink.org.cn/Gitlink/share-knowledge-server/internal/model" + "gitlink.org.cn/Gitlink/share-knowledge-server/pkg/app" +) + +type CountPersonRequest struct { + Name string `form:"name" json:"name" validate:"max=100"` +} + +type GetPersonListRequest struct { + Name string `form:"name" json:"name" validate:"max=100"` + SortBy string `form:"sort_by" json:"sort_by" validate:"oneof='name' 'created_at' ''"` + SortDirection string `form:"sort_direction" json:"sort_direction" validate:"oneof='asc' 'desc' ''"` +} + +type GetPersonRequest struct { + ID int64 `form:"id" json:"id" validate:"required,gte=1"` +} + +type CreatePersonRequest struct { + Name string `form:"name" json:"name" validate:"required"` + Signature string `form:"signature" json:"signature"` +} + +type UpdatePersonRequest struct { + ID int64 `form:"id" json:"id" validate:"required,gte=1"` + Name string `form:"name" json:"name"` + Signature string `form:"signature" json:"signature"` +} + +type DeletePersonRequest struct { + ID int64 `json:"id" validate:"required,gte=1"` +} + +func (svc *Service) CountPerson(param *CountPersonRequest) (int, error) { + return svc.Dao.CountPerson(param.Name) +} + +func (svc *Service) GetPersonList(param *GetPersonListRequest, paper *app.Pager) ([]model.Person, error) { + return svc.Dao.GetPersonList(param.Name, paper.Page, paper.PageSize, param.SortBy, param.SortDirection) +} + +func (svc *Service) GetPerson(param *GetPersonRequest) (model.Person, error) { + return svc.Dao.GetPerson(param.ID) +} + +func (svc *Service) CreatePerson(param *CreatePersonRequest) (model.Person, error) { + return svc.Dao.CreatePerson(param.Name, param.Signature) +} + +func (svc *Service) UpdatePerson(param *UpdatePersonRequest) (model.Person, error) { + return svc.Dao.UpdatePerson(param.ID, param.Name, param.Signature) +} + +func (svc *Service) DeletePerson(param *DeletePersonRequest) (model.Person, error) { + return svc.Dao.DeletePerson(param.ID) +} diff --git a/migrations/000002_create_people.down.sql b/migrations/000002_create_people.down.sql new file mode 100644 index 0000000..105e407 --- /dev/null +++ b/migrations/000002_create_people.down.sql @@ -0,0 +1 @@ +DROP table IF EXISTS people; diff --git a/migrations/000002_create_people.up.sql b/migrations/000002_create_people.up.sql new file mode 100644 index 0000000..fe8b499 --- /dev/null +++ b/migrations/000002_create_people.up.sql @@ -0,0 +1,11 @@ +CREATE TABLE `people` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `created_at` datetime DEFAULT NULL, + `updated_at` datetime DEFAULT NULL, + `deleted_at` datetime DEFAULT NULL, + `name` varchar(255) DEFAULT NULL, + `signature` varchar(255) DEFAULT NULL, + `followed_count` int(11) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_people_deleted_at` (`deleted_at`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;