🎨 优化用户和分类相关接口,新增banner接口

This commit is contained in:
loser 2025-06-23 17:04:44 +08:00
parent a5ae680f94
commit cf0f60d221
29 changed files with 695 additions and 299 deletions

96
api/v1/app/banner.go Normal file
View File

@ -0,0 +1,96 @@
package app
import (
"git.echol.cn/loser/lckt/model/app"
common "git.echol.cn/loser/lckt/model/common/request"
"git.echol.cn/loser/lckt/model/common/response"
"github.com/gin-gonic/gin"
)
type BannerApi struct{}
// Create 新建Banner
func (b *BannerApi) Create(ctx *gin.Context) {
var p app.Banner
if err := ctx.ShouldBind(&p); err != nil {
response.FailWithMessage("参数错误", ctx)
return
}
if err := bannerService.CreateBanner(p); err != nil {
response.FailWithMessage("创建失败: "+err.Error(), ctx)
return
}
response.OkWithMessage("创建成功", ctx)
}
// Delete 删除Banner
func (b *BannerApi) Delete(ctx *gin.Context) {
var p app.Banner
if err := ctx.ShouldBind(&p); err != nil {
response.FailWithMessage("参数错误", ctx)
return
}
if err := bannerService.DeleteBanner(p.ID); err != nil {
response.FailWithMessage("删除失败: "+err.Error(), ctx)
return
}
response.OkWithMessage("删除成功", ctx)
}
// Update 更新Banner
func (b *BannerApi) Update(ctx *gin.Context) {
var p app.Banner
if err := ctx.ShouldBind(&p); err != nil {
response.FailWithMessage("参数错误", ctx)
return
}
if err := bannerService.UpdateBanner(p); err != nil {
response.FailWithMessage("更新失败: "+err.Error(), ctx)
return
}
response.OkWithMessage("更新成功", ctx)
}
// GetList 获取Banner列表
func (b *BannerApi) GetList(ctx *gin.Context) {
var p common.PageInfo
if err := ctx.ShouldBind(&p); err != nil {
response.FailWithMessage("参数错误", ctx)
return
}
list, total, err := bannerService.GetBannerList(p.Page, p.PageSize)
if err != nil {
response.FailWithMessage("获取列表失败: "+err.Error(), ctx)
return
}
response.OkWithData(response.PageResult{
List: list,
Total: total,
Page: p.Page,
PageSize: p.PageSize,
}, ctx)
}
// GetByID 根据ID获取Banner
func (b *BannerApi) GetByID(ctx *gin.Context) {
var p common.GetById
if err := ctx.ShouldBind(&p); err != nil {
response.FailWithMessage("参数错误", ctx)
return
}
banner, err := bannerService.GetBannerByID(p.ID)
if err != nil {
response.FailWithMessage("获取失败: "+err.Error(), ctx)
return
}
response.OkWithData(banner, ctx)
}
func (b *BannerApi) GetIndexBanners(context *gin.Context) {
list, err := bannerService.GetBannerIndex()
if err != nil {
response.FailWithMessage("获取首页Banner失败: "+err.Error(), context)
return
}
response.OkWithData(list, context)
}

12
api/v1/app/enter.go Normal file
View File

@ -0,0 +1,12 @@
package app
import "git.echol.cn/loser/lckt/service"
type ApiGroup struct {
AppUserApi
BannerApi
}
var userService = service.ServiceGroupApp.UserServiceGroup.UserService
var appUserService = service.ServiceGroupApp.AppServiceGroup.AppUserService
var bannerService = service.ServiceGroupApp.AppServiceGroup.BannerService

195
api/v1/app/user.go Normal file
View File

@ -0,0 +1,195 @@
package app
import (
"errors"
"fmt"
"git.echol.cn/loser/lckt/global"
r "git.echol.cn/loser/lckt/model/common/response"
"git.echol.cn/loser/lckt/model/user/request"
"git.echol.cn/loser/lckt/utils"
"git.echol.cn/loser/lckt/utils/user_jwt"
"git.echol.cn/loser/lckt/utils/wechat"
"github.com/gin-gonic/gin"
"github.com/redis/go-redis/v9"
"go.uber.org/zap"
"time"
)
type AppUserApi struct{}
// SendCode 发送验证码
func (*AppUserApi) SendCode(ctx *gin.Context) {
var p request.SendCodeReq
if err := ctx.ShouldBind(&p); err != nil {
r.FailWithMessage(err.Error(), ctx)
global.GVA_LOG.Error("参数错误,发送验证码失败", zap.Error(err))
return
}
if err := userService.SendCode(p); err != nil {
r.FailWithMessage("发送验证码失败", ctx)
return
}
r.OkWithMessage("发送验证码成功", ctx)
}
// Login 用户登录
func (*AppUserApi) Login(ctx *gin.Context) {
var p request.CodeLoginReq
if err := ctx.ShouldBind(&p); err != nil {
r.FailWithMessage(err.Error(), ctx)
global.GVA_LOG.Error("参数错误,登录失败", zap.Error(err))
return
}
if result, _ := global.GVA_REDIS.Get(ctx, fmt.Sprintf("VerifyCode:%s", p.Phone)).Result(); result != p.Code {
global.GVA_LOG.Error("验证码错误", zap.String("phone", p.Phone))
r.FailWithMessage("验证码错误", ctx)
return
}
user, err := appUserService.Login(p)
if err != nil {
r.FailWithMessage("登录失败", ctx)
return
}
// 生成token
token, claims, err := user_jwt.LoginToken(user)
if err != nil {
global.GVA_LOG.Error("获取token失败!", zap.Error(err))
r.FailWithMessage("获取token失败", ctx)
return
}
if _, err = global.GVA_REDIS.Get(ctx, user.Phone).Result(); errors.Is(err, redis.Nil) {
// 此处过期时间等于jwt过期时间
dr, err := utils.ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)
if err != nil {
return
}
timer := dr
if err := global.GVA_REDIS.Set(ctx, user.Phone, token, timer).Err(); err != nil {
global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
r.FailWithMessage("设置登录状态失败", ctx)
return
}
user_jwt.SetToken(ctx, token, int(claims.RegisteredClaims.ExpiresAt.Unix()-time.Now().Unix()))
r.OkWithDetailed(gin.H{
"User": user,
"Token": token,
"ExpiresAt": claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
}, "登录成功", ctx)
} else if err != nil {
global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
r.FailWithMessage("设置登录状态失败", ctx)
}
}
// WechatLogin 微信登录
func (*AppUserApi) WechatLogin(ctx *gin.Context) {
var p request.CodeLoginReq
if err := ctx.ShouldBind(&p); err != nil {
r.FailWithMessage(err.Error(), ctx)
global.GVA_LOG.Error("参数错误,登录失败", zap.Error(err))
return
}
//Todo 待完善微信登录
info := wechat.GetUserInfo(p.Code)
if info == nil {
r.FailWithMessage("获取用户信息失败", ctx)
return
}
user, err := appUserService.WechatLogin(info)
if err != nil {
r.FailWithMessage("登录失败", ctx)
return
}
// 生成token
token, claims, err := user_jwt.LoginToken(user)
if err != nil {
global.GVA_LOG.Error("获取token失败!", zap.Error(err))
r.FailWithMessage("获取token失败", ctx)
return
}
if _, err = global.GVA_REDIS.Get(ctx, user.Phone).Result(); errors.Is(err, redis.Nil) {
// 此处过期时间等于jwt过期时间
dr, err := utils.ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)
if err != nil {
return
}
timer := dr
if err := global.GVA_REDIS.Set(ctx, user.Phone, token, timer).Err(); err != nil {
global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
r.FailWithMessage("设置登录状态失败", ctx)
return
}
user_jwt.SetToken(ctx, token, int(claims.RegisteredClaims.ExpiresAt.Unix()-time.Now().Unix()))
r.OkWithDetailed(gin.H{
"User": user,
"Token": token,
"ExpiresAt": claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
}, "登录成功", ctx)
}
}
// GetUserInfo 获取用户信息
func (*AppUserApi) GetUserInfo(ctx *gin.Context) {
id := user_jwt.GetUserID(ctx)
if id == 0 {
global.GVA_LOG.Error("获取用户ID失败")
r.FailWithMessage("获取用户ID失败", ctx)
return
}
user, err := appUserService.GetUserInfo(id)
if err != nil {
global.GVA_LOG.Error("获取用户信息失败", zap.Error(err))
r.FailWithMessage("获取用户信息失败", ctx)
return
}
r.OkWithDetailed(user, "获取用户信息成功", ctx)
}
// PwdLogin 密码登录
func (*AppUserApi) PwdLogin(ctx *gin.Context) {
var p request.PwdLoginReq
if err := ctx.ShouldBind(&p); err != nil {
r.FailWithMessage(err.Error(), ctx)
global.GVA_LOG.Error("参数错误,登录失败", zap.Error(err))
return
}
user, err := appUserService.PwdLogin(p)
if err != nil {
r.FailWithMessage("手机号或密码错误!", ctx)
return
}
// 生成token
token, claims, err := user_jwt.LoginToken(user)
if err != nil {
global.GVA_LOG.Error("获取token失败!", zap.Error(err))
r.FailWithMessage("获取token失败", ctx)
return
}
// 此处过期时间等于jwt过期时间
dr, err := utils.ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)
if err != nil {
return
}
timer := dr
if err := global.GVA_REDIS.Set(ctx, user.Phone, token, timer).Err(); err != nil {
global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
r.FailWithMessage("设置登录状态失败", ctx)
return
}
user_jwt.SetToken(ctx, token, int(claims.RegisteredClaims.ExpiresAt.Unix()-time.Now().Unix()))
r.OkWithDetailed(gin.H{
"User": user,
"Token": token,
"ExpiresAt": claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
}, "登录成功", ctx)
}

View File

@ -186,3 +186,13 @@ func (catApi *CategoryApi) GetCategoryPublic(c *gin.Context) {
"info": "不需要鉴权的类别接口信息", "info": "不需要鉴权的类别接口信息",
}, "获取成功", c) }, "获取成功", c)
} }
func (catApi *CategoryApi) GetCategoryListPublic(context *gin.Context) {
list, err := catService.GetIndexCategoryList()
if err != nil {
global.GVA_LOG.Error("获取类别列表失败!", zap.Error(err))
response.FailWithMessage("获取类别列表失败:"+err.Error(), context)
return
}
response.OkWithData(list, context)
}

View File

@ -1,6 +1,7 @@
package v1 package v1
import ( import (
"git.echol.cn/loser/lckt/api/v1/app"
"git.echol.cn/loser/lckt/api/v1/article" "git.echol.cn/loser/lckt/api/v1/article"
"git.echol.cn/loser/lckt/api/v1/bot" "git.echol.cn/loser/lckt/api/v1/bot"
"git.echol.cn/loser/lckt/api/v1/category" "git.echol.cn/loser/lckt/api/v1/category"
@ -16,10 +17,11 @@ var ApiGroupApp = new(ApiGroup)
type ApiGroup struct { type ApiGroup struct {
SystemApiGroup system.ApiGroup SystemApiGroup system.ApiGroup
ExampleApiGroup example.ApiGroup ExampleApiGroup example.ApiGroup
AppApiGroup app.ApiGroup
CategoryApiGroup category.ApiGroup CategoryApiGroup category.ApiGroup
BotApiGroup bot.ApiGroup BotApiGroup bot.ApiGroup
ArticleApiGroup article.ApiGroup ArticleApiGroup article.ApiGroup
UserApiGroup user.APPUserApi UserApiGroup user.UserApi
VipApiGroup vip.ApiGroup VipApiGroup vip.ApiGroup
NoticeApiGroup notice.ApiGroup NoticeApiGroup notice.ApiGroup
} }

View File

@ -2,6 +2,6 @@ package user
import "git.echol.cn/loser/lckt/service" import "git.echol.cn/loser/lckt/service"
type ApiGroup struct{ APPUserApi } type ApiGroup struct{ UserApi }
var userService = service.ServiceGroupApp.UserServiceGroup.UserService var userService = service.ServiceGroupApp.UserServiceGroup.UserService

View File

@ -1,141 +1,18 @@
package user package user
import ( import (
"fmt"
"git.echol.cn/loser/lckt/global" "git.echol.cn/loser/lckt/global"
common "git.echol.cn/loser/lckt/model/common/request"
r "git.echol.cn/loser/lckt/model/common/response" r "git.echol.cn/loser/lckt/model/common/response"
"git.echol.cn/loser/lckt/model/user/request" "git.echol.cn/loser/lckt/model/user/request"
"git.echol.cn/loser/lckt/utils"
"git.echol.cn/loser/lckt/utils/user_jwt"
"git.echol.cn/loser/lckt/utils/wechat"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/redis/go-redis/v9"
"go.uber.org/zap" "go.uber.org/zap"
"time"
) )
type APPUserApi struct{} type UserApi struct{}
// SendCode 发送验证码
func (*APPUserApi) SendCode(ctx *gin.Context) {
var p request.SendCodeReq
if err := ctx.ShouldBind(&p); err != nil {
r.FailWithMessage(err.Error(), ctx)
global.GVA_LOG.Error("参数错误,发送验证码失败", zap.Error(err))
return
}
if err := userService.SendCode(p); err != nil {
r.FailWithMessage("发送验证码失败", ctx)
return
}
r.OkWithMessage("发送验证码成功", ctx)
}
// Login 用户登录
func (*APPUserApi) Login(ctx *gin.Context) {
var p request.CodeLoginReq
if err := ctx.ShouldBind(&p); err != nil {
r.FailWithMessage(err.Error(), ctx)
global.GVA_LOG.Error("参数错误,登录失败", zap.Error(err))
return
}
if result, _ := global.GVA_REDIS.Get(ctx, fmt.Sprintf("VerifyCode:%s", p.Phone)).Result(); result != p.Code {
global.GVA_LOG.Error("验证码错误", zap.String("phone", p.Phone))
r.FailWithMessage("验证码错误", ctx)
return
}
user, err := userService.Login(p)
if err != nil {
r.FailWithMessage("登录失败", ctx)
return
}
// 生成token
token, claims, err := user_jwt.LoginToken(user)
if err != nil {
global.GVA_LOG.Error("获取token失败!", zap.Error(err))
r.FailWithMessage("获取token失败", ctx)
return
}
if _, err = global.GVA_REDIS.Get(ctx, user.Phone).Result(); err == redis.Nil {
// 此处过期时间等于jwt过期时间
dr, err := utils.ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)
if err != nil {
return
}
timer := dr
if err := global.GVA_REDIS.Set(ctx, user.Phone, token, timer).Err(); err != nil {
global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
r.FailWithMessage("设置登录状态失败", ctx)
return
}
user_jwt.SetToken(ctx, token, int(claims.RegisteredClaims.ExpiresAt.Unix()-time.Now().Unix()))
r.OkWithDetailed(gin.H{
"User": user,
"Token": token,
"ExpiresAt": claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
}, "登录成功", ctx)
} else if err != nil {
global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
r.FailWithMessage("设置登录状态失败", ctx)
}
}
// WechatLogin 微信登录
func (*APPUserApi) WechatLogin(ctx *gin.Context) {
var p request.CodeLoginReq
if err := ctx.ShouldBind(&p); err != nil {
r.FailWithMessage(err.Error(), ctx)
global.GVA_LOG.Error("参数错误,登录失败", zap.Error(err))
return
}
//Todo 待完善微信登录
info := wechat.GetUserInfo(p.Code)
if info == nil {
r.FailWithMessage("获取用户信息失败", ctx)
return
}
user, err := userService.WechatLogin(info)
if err != nil {
r.FailWithMessage("登录失败", ctx)
return
}
// 生成token
token, claims, err := user_jwt.LoginToken(user)
if err != nil {
global.GVA_LOG.Error("获取token失败!", zap.Error(err))
r.FailWithMessage("获取token失败", ctx)
return
}
if _, err = global.GVA_REDIS.Get(ctx, user.Phone).Result(); err == redis.Nil {
// 此处过期时间等于jwt过期时间
dr, err := utils.ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)
if err != nil {
return
}
timer := dr
if err := global.GVA_REDIS.Set(ctx, user.Phone, token, timer).Err(); err != nil {
global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
r.FailWithMessage("设置登录状态失败", ctx)
return
}
user_jwt.SetToken(ctx, token, int(claims.RegisteredClaims.ExpiresAt.Unix()-time.Now().Unix()))
r.OkWithDetailed(gin.H{
"User": user,
"Token": token,
"ExpiresAt": claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
}, "登录成功", ctx)
}
}
// GetUserList 获取用户列表 // GetUserList 获取用户列表
func (*APPUserApi) GetUserList(ctx *gin.Context) { func (*UserApi) GetUserList(ctx *gin.Context) {
var p request.GetUserListReq var p request.GetUserListReq
if err := ctx.ShouldBind(&p); err != nil { if err := ctx.ShouldBind(&p); err != nil {
r.FailWithMessage(err.Error(), ctx) r.FailWithMessage(err.Error(), ctx)
@ -156,7 +33,7 @@ func (*APPUserApi) GetUserList(ctx *gin.Context) {
} }
// SetBalance 设置用户余额 // SetBalance 设置用户余额
func (*APPUserApi) SetBalance(ctx *gin.Context) { func (*UserApi) SetBalance(ctx *gin.Context) {
var p request.SetBalanceReq var p request.SetBalanceReq
if err := ctx.ShouldBind(&p); err != nil { if err := ctx.ShouldBind(&p); err != nil {
r.FailWithMessage(err.Error(), ctx) r.FailWithMessage(err.Error(), ctx)
@ -170,50 +47,8 @@ func (*APPUserApi) SetBalance(ctx *gin.Context) {
r.OkWithMessage("设置用户余额成功", ctx) r.OkWithMessage("设置用户余额成功", ctx)
} }
// PwdLogin 密码登录
func (*APPUserApi) PwdLogin(ctx *gin.Context) {
var p request.PwdLoginReq
if err := ctx.ShouldBind(&p); err != nil {
r.FailWithMessage(err.Error(), ctx)
global.GVA_LOG.Error("参数错误,登录失败", zap.Error(err))
return
}
user, err := userService.PwdLogin(p)
if err != nil {
r.FailWithMessage("手机号或密码错误!", ctx)
return
}
// 生成token
token, claims, err := user_jwt.LoginToken(user)
if err != nil {
global.GVA_LOG.Error("获取token失败!", zap.Error(err))
r.FailWithMessage("获取token失败", ctx)
return
}
// 此处过期时间等于jwt过期时间
dr, err := utils.ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)
if err != nil {
return
}
timer := dr
if err := global.GVA_REDIS.Set(ctx, user.Phone, token, timer).Err(); err != nil {
global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
r.FailWithMessage("设置登录状态失败", ctx)
return
}
user_jwt.SetToken(ctx, token, int(claims.RegisteredClaims.ExpiresAt.Unix()-time.Now().Unix()))
r.OkWithDetailed(gin.H{
"User": user,
"Token": token,
"ExpiresAt": claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
}, "登录成功", ctx)
}
// Register 注册-后台用 // Register 注册-后台用
func (*APPUserApi) Register(ctx *gin.Context) { func (*UserApi) Register(ctx *gin.Context) {
var p request.RegisterReq var p request.RegisterReq
if err := ctx.ShouldBind(&p); err != nil { if err := ctx.ShouldBind(&p); err != nil {
r.FailWithMessage(err.Error(), ctx) r.FailWithMessage(err.Error(), ctx)
@ -230,7 +65,7 @@ func (*APPUserApi) Register(ctx *gin.Context) {
} }
// SetUserStatus 设置用户状态 // SetUserStatus 设置用户状态
func (*APPUserApi) SetUserStatus(ctx *gin.Context) { func (*UserApi) SetUserStatus(ctx *gin.Context) {
id := ctx.Param("id") id := ctx.Param("id")
if id == "" { if id == "" {
r.FailWithMessage("参数错误", ctx) r.FailWithMessage("参数错误", ctx)
@ -245,7 +80,7 @@ func (*APPUserApi) SetUserStatus(ctx *gin.Context) {
} }
// GetUserById 根据id获取用户信息 // GetUserById 根据id获取用户信息
func (*APPUserApi) GetUserById(ctx *gin.Context) { func (*UserApi) GetUserById(ctx *gin.Context) {
id := ctx.Param("id") id := ctx.Param("id")
if id == "" { if id == "" {
r.FailWithMessage("参数错误", ctx) r.FailWithMessage("参数错误", ctx)
@ -258,3 +93,24 @@ func (*APPUserApi) GetUserById(ctx *gin.Context) {
} }
r.OkWithDetailed(user, "获取用户信息成功", ctx) r.OkWithDetailed(user, "获取用户信息成功", ctx)
} }
func (a *UserApi) GetTeachers(context *gin.Context) {
var p common.PageInfo
if err := context.ShouldBind(&p); err != nil {
r.FailWithMessage(err.Error(), context)
global.GVA_LOG.Error("参数错误,获取教师列表失败", zap.Error(err))
return
}
teachers, total, err := userService.GetTeachers(p)
if err != nil {
r.FailWithMessage("获取教师列表失败", context)
return
}
r.OkWithDetailed(r.PageResult{
List: teachers,
Total: total,
Page: p.Page,
PageSize: p.PageSize,
}, "讲师列表获取成功", context)
}

View File

@ -1,10 +1,10 @@
aliyun-oss: aliyun-oss:
endpoint: yourEndpoint endpoint: oss-cn-hangzhou.aliyuncs.com
access-key-id: yourAccessKeyId access-key-id: LTAI5tB3Mn5Y7mVo8h3zkf46
access-key-secret: yourAccessKeySecret access-key-secret: FtuHdFy4NFdVItEiNBnTun3Ddi8BMK
bucket-name: yourBucketName bucket-name: lckt
bucket-url: yourBucketUrl bucket-url: https://lckt.oss-cn-hangzhou.aliyuncs.com
base-path: yourBasePath base-path: lckt
autocode: autocode:
web: web/src web: web/src
root: C:\Users\Administrator\GolandProjects\zb root: C:\Users\Administrator\GolandProjects\zb
@ -213,7 +213,7 @@ sqlite:
log-zap: false log-zap: false
system: system:
db-type: mysql db-type: mysql
oss-type: local oss-type: aliyun-oss
router-prefix: "" router-prefix: ""
addr: 8888 addr: 8888
iplimit-count: 15000 iplimit-count: 15000

View File

@ -1,6 +1,7 @@
package initialize package initialize
import ( import (
"git.echol.cn/loser/lckt/model/app"
"os" "os"
"git.echol.cn/loser/lckt/global" "git.echol.cn/loser/lckt/global"
@ -62,6 +63,8 @@ func RegisterTables() {
example.ExaFileChunk{}, example.ExaFileChunk{},
example.ExaFileUploadAndDownload{}, example.ExaFileUploadAndDownload{},
example.ExaAttachmentCategory{}, example.ExaAttachmentCategory{},
app.Banner{},
) )
if err != nil { if err != nil {
global.GVA_LOG.Error("register table failed", zap.Error(err)) global.GVA_LOG.Error("register table failed", zap.Error(err))

View File

@ -12,7 +12,14 @@ import (
func bizModel() error { func bizModel() error {
db := global.GVA_DB db := global.GVA_DB
err := db.AutoMigrate(category.Category{}, bot.Bot{}, article.Article{}, user.User{}, vip.Vip{}, notice.Notice{}, notice.Notice{}) err := db.AutoMigrate(
category.Category{},
bot.Bot{},
article.Article{},
user.User{},
vip.Vip{},
notice.Notice{},
)
if err != nil { if err != nil {
return err return err
} }

View File

@ -44,6 +44,7 @@ func Routers() *gin.Engine {
systemRouter := router.RouterGroupApp.System systemRouter := router.RouterGroupApp.System
exampleRouter := router.RouterGroupApp.Example exampleRouter := router.RouterGroupApp.Example
appRouter := router.RouterGroupApp.APP
// 如果想要不使用nginx代理前端网页可以修改 web/.env.production 下的 // 如果想要不使用nginx代理前端网页可以修改 web/.env.production 下的
// VUE_APP_BASE_API = / // VUE_APP_BASE_API = /
// VUE_APP_BASE_PATH = http://localhost // VUE_APP_BASE_PATH = http://localhost
@ -63,10 +64,12 @@ func Routers() *gin.Engine {
// 方便统一添加路由组前缀 多服务器上线使用 // 方便统一添加路由组前缀 多服务器上线使用
PublicGroup := Router.Group(global.GVA_CONFIG.System.RouterPrefix) PublicGroup := Router.Group(global.GVA_CONFIG.System.RouterPrefix)
PublicGroup.Use(middleware.Cors()) // 直接放行全部跨域请求
PrivateGroup := Router.Group(global.GVA_CONFIG.System.RouterPrefix) PrivateGroup := Router.Group(global.GVA_CONFIG.System.RouterPrefix)
PrivateGroup.Use(middleware.JWTAuth()).Use(middleware.CasbinHandler()) PrivateGroup.Use(middleware.JWTAuth()).Use(middleware.CasbinHandler()).Use(middleware.Cors())
AppAuthGroup := Router.Group(global.GVA_CONFIG.System.RouterPrefix)
//AppAuthGroup.Use(middleware.UserJWTAuth()).Use(middleware.Cors())
{ {
// 健康监测 // 健康监测
PublicGroup.GET("/health", func(c *gin.Context) { PublicGroup.GET("/health", func(c *gin.Context) {
@ -99,6 +102,11 @@ func Routers() *gin.Engine {
exampleRouter.InitAttachmentCategoryRouterRouter(PrivateGroup) // 文件上传下载分类 exampleRouter.InitAttachmentCategoryRouterRouter(PrivateGroup) // 文件上传下载分类
} }
//APP相关路由
{
appRouter.InitAppUserRouter(AppAuthGroup, PublicGroup)
appRouter.InitBannerRouter(PrivateGroup, PublicGroup) // Banner相关路由
}
//插件路由安装 //插件路由安装
InstallPlugin(PrivateGroup, PublicGroup, Router) InstallPlugin(PrivateGroup, PublicGroup, Router)

View File

@ -28,7 +28,6 @@ func initBizRouter(routers ...*gin.RouterGroup) {
{ {
userRouter := router.RouterGroupApp.User userRouter := router.RouterGroupApp.User
userRouter.InitUserRouter(privateGroup, publicGroup) userRouter.InitUserRouter(privateGroup, publicGroup)
userRouter.InitAppUserRouter(publicGroup)
} }
{ {
vipRouter := router.RouterGroupApp.Vip vipRouter := router.RouterGroupApp.Vip

16
model/app/banner.go Normal file
View File

@ -0,0 +1,16 @@
package app
import "git.echol.cn/loser/lckt/global"
type Banner struct {
global.GVA_MODEL
Title string `json:"title" gorm:"comment:标题"` // 标题
Link string `json:"link" gorm:"comment:链接"` // 链接
Img string `json:"img" gorm:"comment:图片"` // 图片
Status int `json:"status" gorm:"comment:状态"` // 状态 0:禁用 1:启用
}
// TableName Banner 表名
func (Banner) TableName() string {
return "lckt_banner"
}

17
model/app/vo/user.go Normal file
View File

@ -0,0 +1,17 @@
package vo
type UserInfo struct {
ID uint `json:"id" form:"id"`
NickName string `json:"nick_name" form:"nick_name"`
Phone string `json:"phone" form:"phone" `
UnionId string `json:"union_id" form:"union_id"`
OpenId string `json:"open_id" form:"open_id"`
Avatar string `json:"avatar" form:"avatar"`
InviteCode *string `json:"invite_code" form:"invite_code" gorm:"type:varchar(255) comment '用户专属邀请码'"` // 用户专属邀请码
Balance float32 `json:"balance" form:"balance" gorm:"type:decimal(10,2);comment:学员余额"` // 学员余额
CommenderId int `json:"commender_id" form:"commender_id" gorm:"comment:推荐人ID"` // 推荐人ID
UserLabel int64 `json:"user_label" form:"user_label" gorm:"comment:用户标签 1 普通用户 2 Vip 3 Svip"` // 用户标签 1 普通用户 2 Vip 3 Svip
UserType int8 `json:"user_type" form:"user_type" ` //用户类型 1 用户 2 讲师
IsVip int8 `json:"is_vip" form:"is_vip"` //是否是VIP 0 否 1 是
VipExpireTime string `json:"vip_expire_time" form:"vip_expire_time"` // VIP过期时间
}

View File

@ -6,12 +6,13 @@ import (
type Article struct { type Article struct {
global.GVA_MODEL global.GVA_MODEL
Title string `json:"title" gorm:"comment:文章标题"` Title string `json:"title" gorm:"comment:文章标题"`
Desc string `json:"desc" gorm:"comment:文章描述"` Desc string `json:"desc" gorm:"comment:文章描述"`
Content string `json:"content" gorm:"comment:文章内容"` Content string `json:"content" gorm:"comment:文章内容;type:longtext"`
CoverImg string `json:"coverImg" gorm:"comment:文章封面图"` CoverImg string `json:"coverImg" gorm:"comment:文章封面图"`
TeacherId int `json:"teacherId" gorm:"comment:讲师ID"` TeacherId int `json:"teacherId" gorm:"comment:讲师ID"`
Price int64 `json:"price" gorm:"comment:文章价格(单位为分)"` Price int64 `json:"price" gorm:"comment:文章价格(单位为分)"`
TeacherName string `json:"teacherName" gorm:"comment:讲师名称"`
} }
// TableName 文章表 // TableName 文章表

View File

@ -5,13 +5,15 @@ import (
"git.echol.cn/loser/lckt/global" "git.echol.cn/loser/lckt/global"
) )
// 类别 结构体 Category // Category 分类
type Category struct { type Category struct {
global.GVA_MODEL global.GVA_MODEL
Name *string `json:"name" form:"name" gorm:"column:name;comment:类别名称;" binding:"required"` //名称 Name *string `json:"name" form:"name" gorm:"column:name;comment:类别名称;" binding:"required"` //名称
Order *int `json:"order" form:"order" gorm:"column:order;comment:排序字段;"` //排序 Order *int `json:"order" form:"order" gorm:"column:order;comment:排序字段;"` //排序
Active *bool `json:"active" form:"active" gorm:"column:active;comment:是否激活;"` //状态 Active *bool `json:"active" form:"active" gorm:"column:active;comment:是否激活;"` //状态
ParentId *int `json:"parentId" form:"parentId" gorm:"column:parent_id;comment:父类别ID;"` //父ID ParentId *int `json:"parentId" form:"parentId" gorm:"column:parent_id;comment:父类别ID;"` //父ID
Icon *string `json:"icon" form:"icon" gorm:"column:icon;comment:类别图标;"` //图标
IndexTrue *bool `json:"index" form:"index" gorm:"column:index;comment:是否首页显示;"` //是否首页显示
} }
// TableName 类别 Category自定义表名 categories // TableName 类别 Category自定义表名 categories

22
router/app/banner.go Normal file
View File

@ -0,0 +1,22 @@
package app
import "github.com/gin-gonic/gin"
type BannerRouter struct{}
// InitBannerRouter 初始化 Banner 路由
func (b *BannerRouter) InitBannerRouter(Router, PublicRouter *gin.RouterGroup) {
sysRouter := Router.Group("banner")
appRouter := PublicRouter.Group("banner")
{
sysRouter.POST("", bannerApi.Create) // 新建Banner
sysRouter.DELETE("", bannerApi.Delete) // 删除Banner
sysRouter.PUT("", bannerApi.Update) // 更新Banner
}
{
appRouter.GET("/list", bannerApi.GetList) // 获取Banner列表
appRouter.GET("", bannerApi.GetByID) // Banner公开接口
appRouter.GET("/index", bannerApi.GetIndexBanners) // 获取首页Banner
}
}

11
router/app/enter.go Normal file
View File

@ -0,0 +1,11 @@
package app
import api "git.echol.cn/loser/lckt/api/v1"
type RouterGroup struct {
UserRouter
BannerRouter
}
var userApi = api.ApiGroupApp.AppApiGroup.AppUserApi
var bannerApi = api.ApiGroupApp.AppApiGroup.BannerApi

21
router/app/user.go Normal file
View File

@ -0,0 +1,21 @@
package app
import (
"github.com/gin-gonic/gin"
)
type UserRouter struct{}
func (s *UserRouter) InitAppUserRouter(AppAuthGroup, PublicRouter *gin.RouterGroup) {
appUserRouter := AppAuthGroup.Group("h5_user")
publicRouter := PublicRouter.Group("h5_user")
{
appUserRouter.GET("/info", userApi.GetUserInfo) // 获取用户信息
}
{
publicRouter.POST("wxLogin", userApi.WechatLogin) // 微信登录
publicRouter.POST("pwdlogin", userApi.PwdLogin) // 密码登录
publicRouter.POST("sms/send", userApi.SendCode) // 发送短信验证码
publicRouter.POST("login", userApi.Login) // 短信验证码登录
}
}

View File

@ -20,9 +20,10 @@ func (s *ArticleRouter) InitBotRouter(Router *gin.RouterGroup, PublicRouter *gin
} }
{ {
articleRouterWithoutRecord.GET(":id", artApi.ById) // 根据ID获取文章 articleRouterWithoutRecord.GET(":id", artApi.ById) // 根据ID获取文章
articleRouter.GET("list", artApi.List) // 获取文章列表
} }
{ {
articleRouterWithoutAuth.GET("", artApi.ById) // 文章开放接口 articleRouterWithoutAuth.GET("list", artApi.List) // 获取文章列表
articleRouterWithoutAuth.GET("", artApi.ById) // 文章开放接口
} }
} }

View File

@ -24,5 +24,6 @@ func (s *CategoryRouter) InitCategoryRouter(Router *gin.RouterGroup, PublicRoute
} }
{ {
catRouterWithoutAuth.GET("getCategoryPublic", catApi.GetCategoryPublic) // 类别开放接口 catRouterWithoutAuth.GET("getCategoryPublic", catApi.GetCategoryPublic) // 类别开放接口
catRouterWithoutAuth.GET("/index", catApi.GetCategoryListPublic) // 获取类别列表公开接口
} }
} }

View File

@ -1,6 +1,7 @@
package router package router
import ( import (
"git.echol.cn/loser/lckt/router/app"
"git.echol.cn/loser/lckt/router/article" "git.echol.cn/loser/lckt/router/article"
"git.echol.cn/loser/lckt/router/bot" "git.echol.cn/loser/lckt/router/bot"
"git.echol.cn/loser/lckt/router/category" "git.echol.cn/loser/lckt/router/category"
@ -17,6 +18,7 @@ type RouterGroup struct {
System system.RouterGroup System system.RouterGroup
Example example.RouterGroup Example example.RouterGroup
Category category.RouterGroup Category category.RouterGroup
APP app.RouterGroup
Bot bot.RouterGroup Bot bot.RouterGroup
Article article.RouterGroup Article article.RouterGroup
User user.UserRouter User user.UserRouter

View File

@ -16,16 +16,6 @@ func (s *UserRouter) InitUserRouter(Router *gin.RouterGroup, PublicRouter *gin.R
userRouter.POST("register", userApi.Register) // 注册 userRouter.POST("register", userApi.Register) // 注册
userRouter.PUT("status/:id", userApi.SetUserStatus) // 更新用户状态 userRouter.PUT("status/:id", userApi.SetUserStatus) // 更新用户状态
userRouter.GET(":id", userApi.GetUserById) // 获取用户信息 userRouter.GET(":id", userApi.GetUserById) // 获取用户信息
} userRouter.GET("/teachers", userApi.GetTeachers) // 获取教师列表
}
func (s *UserRouter) InitAppUserRouter(PublicRouter *gin.RouterGroup) {
appUserRouter := PublicRouter.Group("h5_user").Use(middleware.UserJWTAuth())
{
appUserRouter.DELETE("login", userApi.Login) // 短信验证码登录
appUserRouter.POST("sms/send", userApi.SendCode) // 发送短信验证码
appUserRouter.POST("wxLogin", userApi.WechatLogin) // 微信登录
appUserRouter.POST("pwdlogin", userApi.PwdLogin) // 密码登录
appUserRouter.GET(":id", userApi.GetUserById) // 获取用户信息
} }
} }

67
service/app/banner.go Normal file
View File

@ -0,0 +1,67 @@
package app
import (
"git.echol.cn/loser/lckt/global"
"git.echol.cn/loser/lckt/model/app"
"go.uber.org/zap"
)
type BannerService struct{}
// CreateBanner 创建Banner
func (b *BannerService) CreateBanner(p app.Banner) (err error) {
if err = global.GVA_DB.Create(&p).Error; err != nil {
global.GVA_LOG.Error("创建Banner失败!", zap.Error(err))
return
}
return
}
// DeleteBanner 删除Banner
func (b *BannerService) DeleteBanner(id uint) (err error) {
if err = global.GVA_DB.Delete(&app.Banner{}, id).Error; err != nil {
global.GVA_LOG.Error("删除Banner失败!", zap.Error(err))
return
}
return
}
// UpdateBanner 更新Banner
func (b *BannerService) UpdateBanner(p app.Banner) (err error) {
if err = global.GVA_DB.Save(&p).Error; err != nil {
global.GVA_LOG.Error("更新Banner失败!", zap.Error(err))
return
}
return
}
// GetBannerList 获取Banner列表
func (b *BannerService) GetBannerList(page, pageSize int) (list []app.Banner, total int64, err error) {
if err = global.GVA_DB.Model(&app.Banner{}).Count(&total).Error; err != nil {
global.GVA_LOG.Error("获取Banner总数失败!", zap.Error(err))
return
}
if err = global.GVA_DB.Limit(pageSize).Offset((page - 1) * pageSize).Find(&list).Error; err != nil {
global.GVA_LOG.Error("获取Banner列表失败!", zap.Error(err))
return
}
return
}
// GetBannerByID 根据ID获取Banner
func (b *BannerService) GetBannerByID(id int) (banner app.Banner, err error) {
if err = global.GVA_DB.First(&banner, id).Error; err != nil {
global.GVA_LOG.Error("获取Banner失败!", zap.Error(err))
return
}
return
}
func (b *BannerService) GetBannerIndex() (list []app.Banner, err error) {
if err = global.GVA_DB.Where("status = ?", 1).Order("created_at desc").Find(&list).Error; err != nil {
global.GVA_LOG.Error("获取Banner失败!", zap.Error(err))
return
}
return
}

6
service/app/enter.go Normal file
View File

@ -0,0 +1,6 @@
package app
type ServiceGroup struct {
AppUserService
BannerService
}

112
service/app/user.go Normal file
View File

@ -0,0 +1,112 @@
package app
import (
"fmt"
"git.echol.cn/loser/lckt/global"
"git.echol.cn/loser/lckt/model/app/vo"
"git.echol.cn/loser/lckt/model/user"
"git.echol.cn/loser/lckt/model/user/request"
"github.com/ArtisanCloud/PowerSocialite/v3/src/providers"
"go.uber.org/zap"
"golang.org/x/crypto/bcrypt"
)
type AppUserService struct{}
// Login 用户登录
func (u *AppUserService) Login(req request.CodeLoginReq) (users user.User, err error) {
// 1. 判断用户是否存在
var count int64
err = global.GVA_DB.Model(&user.User{}).Where("phone = ?", req.Phone).Count(&count).Error
if err != nil {
global.GVA_LOG.Error("查询用户失败", zap.Error(err))
return
}
// 2. 如果用户不存在,则创建用户
if count == 0 {
user := user.User{
Phone: req.Phone,
UserLabel: 1,
}
err = global.GVA_DB.Save(&user).Error
if err != nil {
global.GVA_LOG.Error("创建用户失败", zap.Error(err))
return
}
} else {
err = global.GVA_DB.Where("phone = ?", req.Phone).First(&users).Error
if err != nil {
global.GVA_LOG.Error("查询用户失败", zap.Error(err))
return
}
}
return
}
// WechatLogin 微信登录
func (u *AppUserService) WechatLogin(info *providers.User) (users user.User, err error) {
openID := info.GetOpenID()
var count int64
// 1. 判断用户是否存在
err = global.GVA_DB.Model(&users).Where("open_id = ?", openID).Count(&count).Error
if err != nil {
global.GVA_LOG.Error("查询用户失败", zap.Error(err))
return
}
if count == 0 {
newUser := user.User{
OpenId: openID,
NickName: info.GetNickname(),
Avatar: info.GetAvatar(),
}
err = global.GVA_DB.Save(&newUser).Error
if err != nil {
global.GVA_LOG.Error("创建用户失败", zap.Error(err))
return
}
return newUser, nil
} else {
err = global.GVA_DB.Where("open_id = ?", openID).First(&users).Error
if err != nil {
global.GVA_LOG.Error("查询用户失败", zap.Error(err))
return
}
}
return
}
// PwdLogin 用户密码登录
func (u *AppUserService) PwdLogin(req request.PwdLoginReq) (users user.User, err error) {
// 1. 判断用户是否存在
var count int64
err = global.GVA_DB.Model(&user.User{}).Where("phone = ?", req.Phone).First(&users).Count(&count).Error
if err != nil {
global.GVA_LOG.Error("查询用户失败", zap.Error(err))
return
}
if count == 0 {
global.GVA_LOG.Error("用户不存在")
err = fmt.Errorf("用户不存在")
return
}
// 2. 判断密码是否正确
err = bcrypt.CompareHashAndPassword([]byte(users.Password), []byte(req.Password))
if err != nil {
global.GVA_LOG.Error("密码错误", zap.Error(err))
return
}
return
}
func (u *AppUserService) GetUserInfo(id uint) (info vo.UserInfo, err error) {
err = global.GVA_DB.Model(&user.User{}).Where("id = ?", id).First(&info).Error
if err != nil {
global.GVA_LOG.Error("查询用户信息失败", zap.Error(err))
return
}
return
}

View File

@ -5,6 +5,7 @@ import (
"git.echol.cn/loser/lckt/global" "git.echol.cn/loser/lckt/global"
"git.echol.cn/loser/lckt/model/category" "git.echol.cn/loser/lckt/model/category"
categoryReq "git.echol.cn/loser/lckt/model/category/request" categoryReq "git.echol.cn/loser/lckt/model/category/request"
"go.uber.org/zap"
) )
type CategoryService struct{} type CategoryService struct{}
@ -83,3 +84,12 @@ func (catService *CategoryService) GetCategoryPublic(ctx context.Context) {
// 此方法为获取数据源定义的数据 // 此方法为获取数据源定义的数据
// 请自行实现 // 请自行实现
} }
func (catService *CategoryService) GetIndexCategoryList() (list []category.Category, err error) {
err = global.GVA_DB.Model(&category.Category{}).Where("categories.index = 1").Find(&list).Error
if err != nil {
global.GVA_LOG.Error("获取首页分类失败", zap.Error(err))
return nil, err
}
return
}

View File

@ -1,6 +1,7 @@
package service package service
import ( import (
"git.echol.cn/loser/lckt/service/app"
"git.echol.cn/loser/lckt/service/article" "git.echol.cn/loser/lckt/service/article"
"git.echol.cn/loser/lckt/service/bot" "git.echol.cn/loser/lckt/service/bot"
"git.echol.cn/loser/lckt/service/category" "git.echol.cn/loser/lckt/service/category"
@ -16,6 +17,7 @@ var ServiceGroupApp = new(ServiceGroup)
type ServiceGroup struct { type ServiceGroup struct {
SystemServiceGroup system.ServiceGroup SystemServiceGroup system.ServiceGroup
ExampleServiceGroup example.ServiceGroup ExampleServiceGroup example.ServiceGroup
AppServiceGroup app.ServiceGroup
CategoryServiceGroup category.ServiceGroup CategoryServiceGroup category.ServiceGroup
BotServiceGroup bot.ServiceGroup BotServiceGroup bot.ServiceGroup
ArticleGroup article.ServiceGroup ArticleGroup article.ServiceGroup

View File

@ -4,10 +4,11 @@ import (
"context" "context"
"fmt" "fmt"
"git.echol.cn/loser/lckt/global" "git.echol.cn/loser/lckt/global"
"git.echol.cn/loser/lckt/model/app/vo"
common "git.echol.cn/loser/lckt/model/common/request"
"git.echol.cn/loser/lckt/model/user" "git.echol.cn/loser/lckt/model/user"
"git.echol.cn/loser/lckt/model/user/request" "git.echol.cn/loser/lckt/model/user/request"
"git.echol.cn/loser/lckt/utils/sms" "git.echol.cn/loser/lckt/utils/sms"
"github.com/ArtisanCloud/PowerSocialite/v3/src/providers"
"go.uber.org/zap" "go.uber.org/zap"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"math/rand" "math/rand"
@ -54,38 +55,6 @@ func (u *UserService) SendCode(req request.SendCodeReq) (err error) {
return return
} }
// Login 用户登录
func (u *UserService) Login(req request.CodeLoginReq) (users user.User, err error) {
// 1. 判断用户是否存在
var count int64
err = global.GVA_DB.Model(&user.User{}).Where("phone = ?", req.Phone).Count(&count).Error
if err != nil {
global.GVA_LOG.Error("查询用户失败", zap.Error(err))
return
}
// 2. 如果用户不存在,则创建用户
if count == 0 {
user := user.User{
Phone: req.Phone,
UserLabel: 1,
}
err = global.GVA_DB.Save(&user).Error
if err != nil {
global.GVA_LOG.Error("创建用户失败", zap.Error(err))
return
}
} else {
err = global.GVA_DB.Where("phone = ?", req.Phone).First(&users).Error
if err != nil {
global.GVA_LOG.Error("查询用户失败", zap.Error(err))
return
}
}
return
}
// GetUserList 获取用户列表 // GetUserList 获取用户列表
func (u *UserService) GetUserList(p request.GetUserListReq) (userList []user.User, total int64, err error) { func (u *UserService) GetUserList(p request.GetUserListReq) (userList []user.User, total int64, err error) {
limit := p.PageSize limit := p.PageSize
@ -130,63 +99,6 @@ func (u *UserService) SetBalance(p request.SetBalanceReq) (err error) {
return return
} }
// WechatLogin 微信登录
func (u *UserService) WechatLogin(info *providers.User) (users user.User, err error) {
openID := info.GetOpenID()
var count int64
// 1. 判断用户是否存在
err = global.GVA_DB.Model(&users).Where("open_id = ?", openID).Count(&count).Error
if err != nil {
global.GVA_LOG.Error("查询用户失败", zap.Error(err))
return
}
if count == 0 {
newUser := user.User{
OpenId: openID,
NickName: info.GetNickname(),
Avatar: info.GetAvatar(),
}
err = global.GVA_DB.Save(&newUser).Error
if err != nil {
global.GVA_LOG.Error("创建用户失败", zap.Error(err))
return
}
return newUser, nil
} else {
err = global.GVA_DB.Where("open_id = ?", openID).First(&users).Error
if err != nil {
global.GVA_LOG.Error("查询用户失败", zap.Error(err))
return
}
}
return
}
// PwdLogin 用户密码登录
func (u *UserService) PwdLogin(req request.PwdLoginReq) (users user.User, err error) {
// 1. 判断用户是否存在
var count int64
err = global.GVA_DB.Model(&user.User{}).Where("phone = ?", req.Phone).First(&users).Count(&count).Error
if err != nil {
global.GVA_LOG.Error("查询用户失败", zap.Error(err))
return
}
if count == 0 {
global.GVA_LOG.Error("用户不存在")
err = fmt.Errorf("用户不存在")
return
}
// 2. 判断密码是否正确
err = bcrypt.CompareHashAndPassword([]byte(users.Password), []byte(req.Password))
if err != nil {
global.GVA_LOG.Error("密码错误", zap.Error(err))
return
}
return
}
// Register 用户注册-后台用 // Register 用户注册-后台用
func (u *UserService) Register(req request.RegisterReq) (err error) { func (u *UserService) Register(req request.RegisterReq) (err error) {
// 1. 判断用户是否存在 // 1. 判断用户是否存在
@ -250,3 +162,18 @@ func (u *UserService) SetUserStatus(id string) (err error) {
} }
return return
} }
func (u *UserService) GetTeachers(p common.PageInfo) (list []vo.UserInfo, total int64, err error) {
limit := p.PageSize
offset := p.PageSize * (p.Page - 1)
// 创建db
db := global.GVA_DB.Model(&user.User{}).Where("user_type = ?", 2)
err = db.Count(&total).Error
if err != nil {
return
}
err = db.Limit(limit).Offset(offset).Find(&list).Error
return
}