feat: rbac迁移完成,并已部署至dev服务器

This commit is contained in:
Blizzard
2026-05-01 01:19:50 +08:00
parent f80a3dc064
commit 8b11068fef
250 changed files with 6314 additions and 13072 deletions
@@ -0,0 +1,45 @@
package logic
import (
"context"
"time"
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/internal/svc"
"sundynix-micro-go/app/system/rpc/system"
"github.com/zeromicro/go-zero/core/logx"
)
type CreateOperationRecordLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewCreateOperationRecordLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateOperationRecordLogic {
return &CreateOperationRecordLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)}
}
func (l *CreateOperationRecordLogic) CreateOperationRecord(in *system.CreateOperationRecordReq) (*system.CommonResp, error) {
record := sysModel.SundynixOperationRecord{
ClientID: in.ClientId,
IP: in.Ip,
Method: in.Method,
Path: in.Path,
Status: int(in.Status),
Latency: time.Duration(in.Latency),
Agent: in.Agent,
ErrorMessage: in.ErrorMessage,
Body: in.Body,
Resp: in.Resp,
UserID: in.UserId,
}
if err := l.svcCtx.DB.Create(&record).Error; err != nil {
l.Errorf("写入操作日志失败: %v", err)
// 日志写入失败不影响业务,不返回error
}
return &system.CommonResp{Code: 200, Msg: "success"}, nil
}
@@ -3,10 +3,13 @@ package logic
import (
"context"
"fmt"
"github.com/zeromicro/go-zero/core/logx"
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/internal/svc"
"sundynix-micro-go/app/system/rpc/system"
"github.com/zeromicro/go-zero/core/logx"
"gorm.io/gorm"
)
type CreateRoleLogic struct {
@@ -20,15 +23,21 @@ func NewCreateRoleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Create
}
func (l *CreateRoleLogic) CreateRole(in *system.RoleReq) (*system.CommonResp, error) {
role := sysModel.SundynixRole{Name: in.Name, Code: in.Code, Sort: int(in.Sort)}
if err := l.svcCtx.DB.Create(&role).Error; err != nil {
return nil, fmt.Errorf("创建角色失败")
}
// 关联菜单
if len(in.MenuIds) > 0 {
for _, mid := range in.MenuIds {
l.svcCtx.DB.Create(&sysModel.SundynixRoleMenu{RoleID: role.ID, MenuID: mid})
err := l.svcCtx.DB.Transaction(func(tx *gorm.DB) error {
role := sysModel.SundynixRole{Name: in.Name, Code: in.Code, Sort: int(in.Sort)}
if err := tx.Create(&role).Error; err != nil {
return fmt.Errorf("创建角色失败: %w", err)
}
// 关联菜单
for _, mid := range in.MenuIds {
if err := tx.Create(&sysModel.SundynixRoleMenu{RoleID: role.ID, MenuID: mid}).Error; err != nil {
return fmt.Errorf("关联菜单失败: %w", err)
}
}
return nil
})
if err != nil {
return nil, err
}
return &system.CommonResp{Code: 200, Msg: "success"}, nil
}
@@ -0,0 +1,62 @@
package logic
import (
"context"
"fmt"
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/internal/svc"
"sundynix-micro-go/app/system/rpc/system"
"sundynix-micro-go/common/utils/hash"
"github.com/zeromicro/go-zero/core/logx"
)
type CreateUserLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewCreateUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateUserLogic {
return &CreateUserLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)}
}
func (l *CreateUserLogic) CreateUser(in *system.CreateUserReq) (*system.CreateUserResp, error) {
// 如果有 OpenId,先查是否已存在(社交登录场景:已有用户直接返回)
if in.OpenId != "" {
var existing sysModel.SundynixUser
if err := l.svcCtx.DB.Where("open_id = ?", in.OpenId).First(&existing).Error; err == nil {
// 用户已存在,更新 session_key 后直接返回
if in.SessionKey != "" {
l.svcCtx.DB.Model(&existing).Update("session_key", in.SessionKey)
}
return &system.CreateUserResp{User: convertUserToProto(&existing)}, nil
}
}
// 如果有 Account,检查是否重复(后台创建用户场景:禁止重复)
if in.Account != "" {
var count int64
l.svcCtx.DB.Model(&sysModel.SundynixUser{}).Where("account = ?", in.Account).Count(&count)
if count > 0 {
return nil, fmt.Errorf("账号 %s 已存在", in.Account)
}
}
u := sysModel.SundynixUser{
Name: in.Name,
Account: in.Account,
Phone: in.Phone,
OpenID: in.OpenId,
SessionKey: in.SessionKey,
ClientID: in.ClientId,
}
if in.Password != "" {
u.Password = hash.BcryptHash(in.Password)
}
if err := l.svcCtx.DB.Create(&u).Error; err != nil {
return nil, fmt.Errorf("创建用户失败: %w", err)
}
return &system.CreateUserResp{User: convertUserToProto(&u)}, nil
}
@@ -3,10 +3,13 @@ package logic
import (
"context"
"fmt"
"github.com/zeromicro/go-zero/core/logx"
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/internal/svc"
"sundynix-micro-go/app/system/rpc/system"
"github.com/zeromicro/go-zero/core/logx"
"gorm.io/gorm"
)
type DeleteMenuLogic struct {
@@ -20,9 +23,17 @@ func NewDeleteMenuLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Delete
}
func (l *DeleteMenuLogic) DeleteMenu(in *system.IdsReq) (*system.CommonResp, error) {
if err := l.svcCtx.DB.Where("id IN ?", in.Ids).Delete(&sysModel.SundynixMenu{}).Error; err != nil {
return nil, fmt.Errorf("删除菜单失败")
err := l.svcCtx.DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Where("id IN ?", in.Ids).Delete(&sysModel.SundynixMenu{}).Error; err != nil {
return fmt.Errorf("删除菜单失败: %w", err)
}
if err := tx.Where("menu_id IN ?", in.Ids).Delete(&sysModel.SundynixRoleMenu{}).Error; err != nil {
return fmt.Errorf("清除角色关联失败: %w", err)
}
return nil
})
if err != nil {
return nil, err
}
l.svcCtx.DB.Where("menu_id IN ?", in.Ids).Delete(&sysModel.SundynixRoleMenu{})
return &system.CommonResp{Code: 200, Msg: "success"}, nil
}
@@ -3,10 +3,13 @@ package logic
import (
"context"
"fmt"
"github.com/zeromicro/go-zero/core/logx"
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/internal/svc"
"sundynix-micro-go/app/system/rpc/system"
"github.com/zeromicro/go-zero/core/logx"
"gorm.io/gorm"
)
type DeleteRoleLogic struct {
@@ -20,9 +23,17 @@ func NewDeleteRoleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Delete
}
func (l *DeleteRoleLogic) DeleteRole(in *system.IdsReq) (*system.CommonResp, error) {
if err := l.svcCtx.DB.Where("id IN ?", in.Ids).Delete(&sysModel.SundynixRole{}).Error; err != nil {
return nil, fmt.Errorf("删除角色失败")
err := l.svcCtx.DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Where("id IN ?", in.Ids).Delete(&sysModel.SundynixRole{}).Error; err != nil {
return fmt.Errorf("删除角色失败: %w", err)
}
if err := tx.Where("role_id IN ?", in.Ids).Delete(&sysModel.SundynixRoleMenu{}).Error; err != nil {
return fmt.Errorf("清除菜单关联失败: %w", err)
}
return nil
})
if err != nil {
return nil, err
}
l.svcCtx.DB.Where("role_id IN ?", in.Ids).Delete(&sysModel.SundynixRoleMenu{})
return &system.CommonResp{Code: 200, Msg: "success"}, nil
}
@@ -0,0 +1,39 @@
package logic
import (
"context"
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/internal/svc"
"sundynix-micro-go/app/system/rpc/system"
"github.com/zeromicro/go-zero/core/logx"
"gorm.io/gorm"
)
type DeleteUserLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewDeleteUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteUserLogic {
return &DeleteUserLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)}
}
func (l *DeleteUserLogic) DeleteUser(in *system.DeleteUserReq) (*system.CommonResp, error) {
err := l.svcCtx.DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Where("id IN ?", in.Ids).Delete(&sysModel.SundynixUser{}).Error; err != nil {
return err
}
// 同时删除用户角色关联
if err := tx.Where("user_id IN ?", in.Ids).Delete(&sysModel.SundynixUserRole{}).Error; err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return &system.CommonResp{Code: 200, Msg: "success"}, nil
}
@@ -2,6 +2,7 @@ package logic
import (
"context"
"errors"
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/internal/svc"
@@ -32,10 +33,11 @@ func (l *GetClientByIdLogic) GetClientById(in *system.GetClientByIdReq) (*system
var client sysModel.SundynixClient
err := l.svcCtx.DB.Where("client_id = ?", in.ClientId).First(&client).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
if errors.Is(err, gorm.ErrRecordNotFound) {
l.Infof("[GetClientById] 客户端不存在 | clientId=%s", in.ClientId)
return nil, status.Error(codes.NotFound, "客户端不存在")
}
l.Errorf("查询客户端失败: %v", err)
l.Errorf("[GetClientById] ❌ 查询客户端失败 | clientId=%s | err=%v", in.ClientId, err)
return nil, status.Error(codes.Internal, "查询客户端失败")
}
@@ -3,10 +3,11 @@ package logic
import (
"context"
"fmt"
"github.com/zeromicro/go-zero/core/logx"
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/internal/svc"
"sundynix-micro-go/app/system/rpc/system"
"github.com/zeromicro/go-zero/core/logx"
)
type GetMenuListLogic struct {
@@ -22,9 +23,11 @@ func NewGetMenuListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetMe
func (l *GetMenuListLogic) GetMenuList(in *system.IdReq) (*system.MenuListResp, error) {
var menus []sysModel.SundynixMenu
if err := l.svcCtx.DB.Order("sort ASC").Find(&menus).Error; err != nil {
l.Errorf("[GetMenuList] ❌ 查询菜单失败: %v", err)
return nil, fmt.Errorf("查询菜单列表失败")
}
tree := buildMenuTree(menus, "")
l.Infof("[GetMenuList] 查询到菜单数量: %d", len(menus))
tree := buildMenuTree(menus, "0")
return &system.MenuListResp{Menus: tree}, nil
}
@@ -73,7 +73,8 @@ func (l *GetMenusByRoleIdLogic) GetMenusByRoleId(in *system.GetMenusByRoleIdReq)
menuMap[m.ID] = menuInfo
}
for _, menuInfo := range menuMap {
for _, m := range menus {
menuInfo := menuMap[m.ID]
if menuInfo.ParentId == "0" || menuInfo.ParentId == "" {
rootMenus = append(rootMenus, menuInfo)
} else {
@@ -46,11 +46,21 @@ func (l *GetOperationRecordListLogic) GetOperationRecordList(in *system.Operatio
var items []*system.OperationRecordInfo
for _, r := range list {
items = append(items, &system.OperationRecordInfo{
Id: r.ID, Ip: r.IP, Method: r.Method, Path: r.Path,
Status: int32(r.Status), Agent: r.Agent, ErrorMessage: r.ErrorMessage,
Body: r.Body, Resp: r.Resp, UserId: r.UserID,
CreatedAt: r.CreatedAt.Unix(),
Id: r.ID,
ClientId: r.ClientID,
Ip: r.IP,
Method: r.Method,
Path: r.Path,
Status: int32(r.Status),
Latency: int64(r.Latency),
Agent: r.Agent,
ErrorMessage: r.ErrorMessage,
Body: r.Body,
Resp: r.Resp,
UserId: r.UserID,
CreatedAt: r.CreatedAt.Unix(),
})
}
return &system.OperationRecordListResp{List: items, Total: total}, nil
}
@@ -0,0 +1,36 @@
package logic
import (
"context"
"errors"
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/internal/svc"
"sundynix-micro-go/app/system/rpc/system"
"github.com/zeromicro/go-zero/core/logx"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"gorm.io/gorm"
)
type GetUserByIdLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewGetUserByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserByIdLogic {
return &GetUserByIdLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)}
}
func (l *GetUserByIdLogic) GetUserById(in *system.GetUserByIdReq) (*system.GetUserByIdResp, error) {
var u sysModel.SundynixUser
if err := l.svcCtx.DB.Where("id = ?", in.Id).First(&u).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, status.Error(codes.NotFound, "用户不存在")
}
return nil, status.Error(codes.Internal, "查询用户失败")
}
return &system.GetUserByIdResp{User: convertUserToProto(&u)}, nil
}
@@ -0,0 +1,36 @@
package logic
import (
"context"
"errors"
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/internal/svc"
"sundynix-micro-go/app/system/rpc/system"
"github.com/zeromicro/go-zero/core/logx"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"gorm.io/gorm"
)
type GetUserByOpenIdLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewGetUserByOpenIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserByOpenIdLogic {
return &GetUserByOpenIdLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)}
}
func (l *GetUserByOpenIdLogic) GetUserByOpenId(in *system.GetUserByOpenIdReq) (*system.GetUserByOpenIdResp, error) {
var u sysModel.SundynixUser
if err := l.svcCtx.DB.Where("open_id = ?", in.OpenId).First(&u).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, status.Error(codes.NotFound, "用户不存在")
}
return nil, status.Error(codes.Internal, "查询失败")
}
return &system.GetUserByOpenIdResp{User: convertUserToProto(&u)}, nil
}
@@ -0,0 +1,51 @@
package logic
import (
"context"
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/internal/svc"
"sundynix-micro-go/app/system/rpc/system"
"github.com/zeromicro/go-zero/core/logx"
)
type GetUserListLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewGetUserListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserListLogic {
return &GetUserListLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)}
}
func (l *GetUserListLogic) GetUserList(in *system.GetUserListReq) (*system.GetUserListResp, error) {
db := l.svcCtx.DB.Model(&sysModel.SundynixUser{})
if in.Name != "" {
db = db.Where("name LIKE ?", "%"+in.Name+"%")
}
if in.Account != "" {
db = db.Where("account LIKE ?", "%"+in.Account+"%")
}
var total int64
db.Count(&total)
var list []sysModel.SundynixUser
pageSize := int(in.PageSize)
if pageSize <= 0 {
pageSize = 10
}
current := int(in.Current)
if current <= 0 {
current = 1
}
db.Offset((current - 1) * pageSize).Limit(pageSize).Order("created_at DESC").Find(&list)
var protoList []*system.UserInfo
for _, u := range list {
protoList = append(protoList, convertUserToProto(&u))
}
return &system.GetUserListResp{List: protoList, Total: total}, nil
}
@@ -0,0 +1,48 @@
package logic
import (
"context"
"errors"
"time"
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/internal/svc"
"sundynix-micro-go/app/system/rpc/system"
"sundynix-micro-go/common/utils/hash"
"github.com/zeromicro/go-zero/core/logx"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"gorm.io/gorm"
)
type LoginByAccountLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewLoginByAccountLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LoginByAccountLogic {
return &LoginByAccountLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)}
}
func (l *LoginByAccountLogic) LoginByAccount(in *system.LoginByAccountReq) (*system.LoginByAccountResp, error) {
var u sysModel.SundynixUser
err := l.svcCtx.DB.Where("account = ?", in.Account).First(&u).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, status.Error(codes.NotFound, "账号不存在")
}
return nil, status.Error(codes.Internal, "查询用户失败")
}
if !hash.BcryptCheck(in.Password, u.Password) {
return nil, status.Error(codes.Unauthenticated, "密码错误")
}
// 更新最后登录时间
now := time.Now()
l.svcCtx.DB.Model(&u).Update("last_login_at", now)
u.LastLoginAt = &now
return &system.LoginByAccountResp{User: convertUserToProto(&u)}, nil
}
@@ -0,0 +1,30 @@
package logic
import (
"context"
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/internal/svc"
"sundynix-micro-go/app/system/rpc/system"
"sundynix-micro-go/common/utils/hash"
"github.com/zeromicro/go-zero/core/logx"
)
type ResetPasswordLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewResetPasswordLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ResetPasswordLogic {
return &ResetPasswordLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)}
}
func (l *ResetPasswordLogic) ResetPassword(in *system.ResetPasswordReq) (*system.CommonResp, error) {
if err := l.svcCtx.DB.Model(&sysModel.SundynixUser{}).Where("id = ?", in.Id).
Update("password", hash.BcryptHash(in.Password)).Error; err != nil {
return nil, err
}
return &system.CommonResp{Code: 200, Msg: "success"}, nil
}
@@ -3,10 +3,13 @@ package logic
import (
"context"
"fmt"
"github.com/zeromicro/go-zero/core/logx"
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/internal/svc"
"sundynix-micro-go/app/system/rpc/system"
"github.com/zeromicro/go-zero/core/logx"
"gorm.io/gorm"
)
type UpdateRoleLogic struct {
@@ -20,15 +23,26 @@ func NewUpdateRoleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Update
}
func (l *UpdateRoleLogic) UpdateRole(in *system.RoleUpdateReq) (*system.CommonResp, error) {
if err := l.svcCtx.DB.Model(&sysModel.SundynixRole{}).Where("id = ?", in.Id).Updates(map[string]interface{}{
"name": in.Name, "code": in.Code, "sort": in.Sort,
}).Error; err != nil {
return nil, fmt.Errorf("更新角色失败")
}
// 更新菜单关联
l.svcCtx.DB.Where("role_id = ?", in.Id).Delete(&sysModel.SundynixRoleMenu{})
for _, mid := range in.MenuIds {
l.svcCtx.DB.Create(&sysModel.SundynixRoleMenu{RoleID: in.Id, MenuID: mid})
err := l.svcCtx.DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Model(&sysModel.SundynixRole{}).Where("id = ?", in.Id).Updates(map[string]interface{}{
"name": in.Name, "code": in.Code, "sort": in.Sort,
}).Error; err != nil {
return fmt.Errorf("更新角色失败: %w", err)
}
// 先删除旧的菜单关联
if err := tx.Where("role_id = ?", in.Id).Delete(&sysModel.SundynixRoleMenu{}).Error; err != nil {
return fmt.Errorf("清除菜单关联失败: %w", err)
}
// 重新关联菜单
for _, mid := range in.MenuIds {
if err := tx.Create(&sysModel.SundynixRoleMenu{RoleID: in.Id, MenuID: mid}).Error; err != nil {
return fmt.Errorf("关联菜单失败: %w", err)
}
}
return nil
})
if err != nil {
return nil, err
}
return &system.CommonResp{Code: 200, Msg: "success"}, nil
}
@@ -0,0 +1,44 @@
package logic
import (
"context"
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/internal/svc"
"sundynix-micro-go/app/system/rpc/system"
"github.com/zeromicro/go-zero/core/logx"
)
type UpdateUserLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewUpdateUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateUserLogic {
return &UpdateUserLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)}
}
func (l *UpdateUserLogic) UpdateUser(in *system.UpdateUserReq) (*system.CommonResp, error) {
updates := map[string]interface{}{}
if in.Name != "" {
updates["name"] = in.Name
}
if in.Account != "" {
updates["account"] = in.Account
}
if in.Phone != "" {
updates["phone"] = in.Phone
}
if in.AvatarId != "" {
updates["avatar_id"] = in.AvatarId
}
if in.NickName != "" {
updates["nick_name"] = in.NickName
}
if err := l.svcCtx.DB.Model(&sysModel.SundynixUser{}).Where("id = ?", in.Id).Updates(updates).Error; err != nil {
return nil, err
}
return &system.CommonResp{Code: 200, Msg: "success"}, nil
}
@@ -0,0 +1,31 @@
package logic
import (
sysModel "sundynix-micro-go/app/system/model"
"sundynix-micro-go/app/system/rpc/system"
)
// convertUserToProto 将 model 转为 proto UserInfo
func convertUserToProto(u *sysModel.SundynixUser) *system.UserInfo {
info := &system.UserInfo{
Id: u.ID,
TenantId: u.TenantID,
ClientId: u.ClientID,
Name: u.Name,
Account: u.Account,
NickName: u.NickName,
Phone: u.Phone,
SessionKey: u.SessionKey,
UnionId: u.UnionID,
OpenId: u.OpenID,
SaOpenId: u.SaOpenID,
AvatarId: u.AvatarID,
Gender: int32(u.Gender),
CreatedAt: u.CreatedAt.Unix(),
UpdatedAt: u.UpdatedAt.Unix(),
}
if u.LastLoginAt != nil {
info.LastLoginAt = u.LastLoginAt.Unix()
}
return info
}