package model import ( "fmt" "strings" "time" "github.com/alexandrevicenzi/unchained" "go.uber.org/zap" "gorm.io/gorm" ) type User struct { Id int64 `form:"id" json:"id,omitempty" gorm:"primaryKey;autoIncrement;column:id;comment:用户 id;"` Username string `form:"username" json:"username,omitempty" gorm:"column:username;type:varchar(64);size:64;index:username,unique;comment:用户名;"` Password string `form:"password" json:"password,omitempty" gorm:"column:password;type:varchar(128);size:128;comment:密码;"` Mobile string `form:"mobile" json:"mobile,omitempty" gorm:"column:mobile;type:varchar(20);size:20;index:mobile;comment:手机号;"` Email string `form:"email" json:"email,omitempty" gorm:"column:email;type:varchar(64);size:64;index:email;comment:联系邮箱;"` Address string `form:"address" json:"address,omitempty" gorm:"column:address;type:varchar(255);size:255;comment:联系地址;"` Signature string `form:"signature" json:"signature,omitempty" gorm:"column:signature;type:varchar(255);size:255;comment:签名;"` LastLoginIp string `form:"last_login_ip" json:"last_login_ip,omitempty" gorm:"column:last_login_ip;type:varchar(32);size:32;comment:最后登录 ip 地址;"` RegisterIp string `form:"register_ip" json:"register_ip,omitempty" gorm:"column:register_ip;type:varchar(32);size:32;comment:注册ip;"` DocCount int `form:"doc_count" json:"doc_count,omitempty" gorm:"column:doc_count;type:int(10) unsigned;default:0;comment:上传的文档数;"` FollowCount int `form:"follow_count" json:"follow_count,omitempty" gorm:"column:follow_count;type:int(10) unsigned;default:0;comment:关注数;"` FansCount int `form:"fans_count" json:"fans_count,omitempty" gorm:"column:fans_count;type:int(10) unsigned;default:0;comment:粉丝数;"` FavoriteCount int `form:"favorite_count" json:"favorite_count,omitempty" gorm:"column:favorite_count;type:int(10) unsigned;default:0;comment:收藏数;"` CommentCount int `form:"comment_count" json:"comment_count,omitempty" gorm:"column:comment_count;type:int(11);size:11;default:0;comment:评论数;"` Status int8 `form:"status" json:"status,omitempty" gorm:"column:status;type:tinyint(4);size:4;default:0;index:status;comment:用户状态:0正常 1禁用 2审核中 3审核拒绝 4审核忽略;"` Avatar string `form:"avatar" json:"avatar,omitempty" gorm:"column:avatar;type:varchar(255);size:255;comment:头像;"` Identity string `form:"identity" json:"identity,omitempty" gorm:"column:identity;type:char(18);size:18;comment:身份证号码;"` Realname string `form:"realname" json:"realname,omitempty" gorm:"column:realname;type:varchar(20);size:20;comment:身份证姓名;"` LoginAt time.Time `form:"login_at" json:"login_at,omitempty" gorm:"column:login_at;type:datetime;comment:最后登录时间;"` CreatedAt time.Time `form:"created_at" json:"created_at,omitempty" gorm:"column:created_at;type:datetime;comment:创建时间;"` UpdatedAt time.Time `form:"updated_at" json:"updated_at,omitempty" gorm:"column:updated_at;type:datetime;comment:更新时间;"` } // 这里是proto文件中的结构体,可以根据需要删除或者调整 //message User { // int64 id = 1; // string username = 2; // string password = 3; // string nickname = 4; // string mobile = 5; // string email = 6; // string address = 7; // string signature = 8; // string last_login_ip = 9; // string register_ip = 10; // int32 doc_count = 11; // int32 follow_count = 12; // int32 fans_count = 13; // int32 favorite_count = 14; // int32 comment_count = 15; // int32 status = 16; // string avatar = 17; // string identity = 18; // string realname = 19; // google.protobuf.Timestamp login_at = 20 [ (gogoproto.stdtime) = true ]; // google.protobuf.Timestamp created_at = 21 [ (gogoproto.stdtime) = true ]; // google.protobuf.Timestamp updated_at = 22 [ (gogoproto.stdtime) = true ]; //} func (User) TableName() string { return tablePrefix + "user" } // CreateUser 创建User // TODO: 创建成功之后,注意相关表统计字段数值的增减 func (m *DBModel) CreateUser(user *User, groupId int64) (err error) { user.Password, _ = unchained.MakePassword(user.Password, unchained.GetRandomString(4), "md5") sess := m.db.Begin() defer func() { if err != nil { sess.Rollback() } else { sess.Commit() } }() // 1. 添加用户 err = sess.Create(user).Error if err != nil { m.logger.Error("CreateUser", zap.Error(err)) return } // 2. 添加用户组 group := &UserGroup{ UserId: user.Id, GroupId: groupId, } err = sess.Create(group).Error if err != nil { m.logger.Error("CreateUser", zap.Error(err)) return } // 3. 添加用户统计 err = sess.Model(&Group{}).Where("id = ?", groupId).Update("user_count", gorm.Expr("user_count + ?", 1)).Error if err != nil { m.logger.Error("CreateUser", zap.Error(err)) return } return } // UpdateUserPassword 更新User密码 func (m *DBModel) UpdateUserPassword(id interface{}, newPassword string) (err error) { newPassword, _ = unchained.MakePassword(newPassword, unchained.GetRandomString(4), "md5") err = m.db.Model(&User{}).Where("id = ?", id).Update("password", newPassword).Error if err != nil { m.logger.Error("UpdateUserPassword", zap.Error(err)) } return } // UpdateUser 更新User,如果需要更新指定字段,则请指定updateFields参数 func (m *DBModel) UpdateUser(user *User, updateFields ...string) (err error) { db := m.db.Model(user) updateFields = m.FilterValidFields(User{}.TableName(), updateFields...) if len(updateFields) > 0 { // 更新指定字段 db = db.Select(updateFields) } err = db.Where("id = ?", user.Id).Updates(user).Error if err != nil { m.logger.Error("UpdateUser", zap.Error(err)) } return } // GetUser 根据id获取User func (m *DBModel) GetUser(id interface{}, fields ...string) (user User, err error) { db := m.db fields = m.FilterValidFields(User{}.TableName(), fields...) if len(fields) > 0 { db = db.Select(fields) } err = db.Where("id = ?", id).First(&user).Error return } // GetUserByUsername(username string, fields ...string) 根据唯一索引获取User func (m *DBModel) GetUserByUsername(username string, fields ...string) (user User, err error) { db := m.db fields = m.FilterValidFields(User{}.TableName(), fields...) if len(fields) > 0 { db = db.Select(fields) } db = db.Where("username = ?", username) err = db.First(&user).Error if err != nil && err != gorm.ErrRecordNotFound { m.logger.Error("GetUserByUsername", zap.Error(err)) return } return } type OptionGetUserList struct { Page int Size int WithCount bool // 是否返回总数 Ids []interface{} // id列表 SelectFields []string // 查询字段 QueryRange map[string][2]interface{} // map[field][]{min,max} QueryIn map[string][]interface{} // map[field][]{value1,value2,...} QueryLike map[string][]interface{} // map[field][]{value1,value2,...} Sort []string } // GetUserList 获取User列表 func (m *DBModel) GetUserList(opt OptionGetUserList) (userList []User, total int64, err error) { db := m.db.Model(&User{}) for field, rangeValue := range opt.QueryRange { fields := m.FilterValidFields(User{}.TableName(), field) if len(fields) == 0 { continue } if rangeValue[0] != nil { db = db.Where(fmt.Sprintf("%s >= ?", field), rangeValue[0]) } if rangeValue[1] != nil { db = db.Where(fmt.Sprintf("%s <= ?", field), rangeValue[1]) } } for field, values := range opt.QueryIn { fields := m.FilterValidFields(User{}.TableName(), field) if len(fields) == 0 { continue } db = db.Where(fmt.Sprintf("%s in (?)", field), values) } for field, values := range opt.QueryLike { fields := m.FilterValidFields(User{}.TableName(), field) if len(fields) == 0 { continue } db = db.Where(strings.TrimSuffix(fmt.Sprintf(strings.Join(make([]string, len(values)+1), "%s like ? or"), field), "or"), values...) } if len(opt.Ids) > 0 { db = db.Where("id in (?)", opt.Ids) } if opt.WithCount { err = db.Count(&total).Error if err != nil { m.logger.Error("GetUserList", zap.Error(err)) return } } opt.SelectFields = m.FilterValidFields(User{}.TableName(), opt.SelectFields...) if len(opt.SelectFields) > 0 { db = db.Select(opt.SelectFields) } if len(opt.Sort) > 0 { var sorts []string for _, sort := range opt.Sort { slice := strings.Split(sort, " ") if len(m.FilterValidFields(User{}.TableName(), slice[0])) == 0 { continue } if len(slice) == 2 { sorts = append(sorts, fmt.Sprintf("%s %s", slice[0], slice[1])) } else { sorts = append(sorts, fmt.Sprintf("%s desc", slice[0])) } } if len(sorts) > 0 { db = db.Order(strings.Join(sorts, ",")) } } db = db.Offset((opt.Page - 1) * opt.Size).Limit(opt.Size) err = db.Find(&userList).Error if err != nil && err != gorm.ErrRecordNotFound { m.logger.Error("GetUserList", zap.Error(err)) } return } // DeleteUser 删除数据 // TODO: 删除数据之后,存在 user_id 的关联表,需要删除对应数据,同时相关表的统计数值,也要随着减少 func (m *DBModel) DeleteUser(ids []interface{}) (err error) { err = m.db.Where("id in (?)", ids).Delete(&User{}).Error if err != nil { m.logger.Error("DeleteUser", zap.Error(err)) } return } func (m *DBModel) initUser() (err error) { // 如果不存在任意用户,则初始化一个用户作为管理员 var existUser User m.db.Select("id").First(&existUser) if existUser.Id > 0 { return } // 初始化一个用户 user := &User{Username: "admin", Password: "123456"} groupId := 1 // ID==1的用户组为管理员组 err = m.CreateUser(user, int64(groupId)) if err != nil { m.logger.Error("initUser", zap.Error(err)) } return }