2025-04-09 16:34:41 +08:00
|
|
|
package handlers
|
|
|
|
|
|
|
|
|
|
import (
|
2025-04-18 16:22:38 +08:00
|
|
|
"platform/web/auth"
|
2025-12-30 19:24:03 +08:00
|
|
|
"platform/web/core"
|
|
|
|
|
g "platform/web/globals"
|
2025-04-29 18:48:14 +08:00
|
|
|
m "platform/web/models"
|
2025-04-09 16:34:41 +08:00
|
|
|
q "platform/web/queries"
|
2025-04-18 16:22:38 +08:00
|
|
|
s "platform/web/services"
|
2025-11-17 18:38:10 +08:00
|
|
|
|
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
2025-04-09 16:34:41 +08:00
|
|
|
)
|
|
|
|
|
|
2025-12-30 19:24:03 +08:00
|
|
|
// 分页获取用户
|
|
|
|
|
func PageUserByAdmin(c *fiber.Ctx) error {
|
|
|
|
|
// 检查权限
|
|
|
|
|
_, err := auth.GetAuthCtx(c).PermitAdmin()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2025-04-29 18:48:14 +08:00
|
|
|
|
2025-12-30 19:24:03 +08:00
|
|
|
// 解析请求参数
|
2026-03-23 14:26:10 +08:00
|
|
|
req := new(PageUserByAdminReq)
|
2025-12-30 19:24:03 +08:00
|
|
|
if err := g.Validator.ParseBody(c, req); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-23 14:26:10 +08:00
|
|
|
// 构建查询条件
|
|
|
|
|
do := q.User.Where()
|
2026-03-27 16:16:55 +08:00
|
|
|
if req.Account != nil {
|
|
|
|
|
do = do.Where(q.User.Where(
|
|
|
|
|
q.User.Username.Like("%" + *req.Account + "%"),
|
|
|
|
|
).Or(
|
|
|
|
|
q.User.Phone.Like("%" + *req.Account + "%"),
|
|
|
|
|
).Or(
|
|
|
|
|
q.User.Email.Like("%" + *req.Account + "%"),
|
|
|
|
|
))
|
2026-03-23 14:26:10 +08:00
|
|
|
}
|
|
|
|
|
if req.Name != nil {
|
|
|
|
|
do = do.Where(q.User.Name.Eq(*req.Name))
|
|
|
|
|
}
|
|
|
|
|
if req.Identified != nil {
|
|
|
|
|
if *req.Identified {
|
|
|
|
|
do = do.Where(q.User.IDType.Gt(0))
|
|
|
|
|
} else {
|
|
|
|
|
do = do.Where(q.User.IDType.Eq(0))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if req.Enabled != nil {
|
|
|
|
|
if *req.Enabled {
|
|
|
|
|
do = do.Where(q.User.Status.Eq(1))
|
|
|
|
|
} else {
|
|
|
|
|
do = do.Where(q.User.Status.Eq(0))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if req.Assigned != nil {
|
|
|
|
|
if *req.Assigned {
|
|
|
|
|
do = do.Where(q.User.AdminID.IsNotNull())
|
|
|
|
|
} else {
|
|
|
|
|
do = do.Where(q.User.AdminID.IsNull())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-30 19:24:03 +08:00
|
|
|
// 查询用户列表
|
2026-03-27 16:16:55 +08:00
|
|
|
users, total, err := q.User.Debug().
|
2026-01-09 18:52:48 +08:00
|
|
|
Preload(q.User.Admin).
|
2025-12-30 19:24:03 +08:00
|
|
|
Omit(q.User.Password).
|
2026-03-23 14:26:10 +08:00
|
|
|
Where(do).
|
2025-12-30 19:24:03 +08:00
|
|
|
FindByPage(req.GetOffset(), req.GetLimit())
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-09 18:52:48 +08:00
|
|
|
for _, user := range users {
|
|
|
|
|
if user.Admin != nil {
|
|
|
|
|
user.Admin = &m.Admin{
|
|
|
|
|
Name: user.Admin.Name,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-30 19:24:03 +08:00
|
|
|
// 返回结果
|
|
|
|
|
return c.JSON(core.PageResp{
|
|
|
|
|
Total: int(total),
|
|
|
|
|
Page: req.GetPage(),
|
|
|
|
|
Size: req.GetSize(),
|
|
|
|
|
List: users,
|
|
|
|
|
})
|
2025-04-29 18:48:14 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-23 14:26:10 +08:00
|
|
|
type PageUserByAdminReq struct {
|
|
|
|
|
core.PageReq
|
2026-03-27 16:16:55 +08:00
|
|
|
Account *string `json:"account,omitempty"`
|
2026-03-23 14:26:10 +08:00
|
|
|
Name *string `json:"name,omitempty"`
|
|
|
|
|
Identified *bool `json:"identified,omitempty"`
|
|
|
|
|
Enabled *bool `json:"enabled,omitempty"`
|
|
|
|
|
Assigned *bool `json:"assigned,omitempty"`
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-06 15:33:55 +08:00
|
|
|
// 绑定管理员
|
|
|
|
|
func BindAdmin(c *fiber.Ctx) error {
|
|
|
|
|
// 检查权限
|
|
|
|
|
authCtx, err := auth.GetAuthCtx(c).PermitAdmin()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解析请求参数
|
|
|
|
|
req := new(struct {
|
|
|
|
|
UserID int `json:"user_id" validate:"required"`
|
|
|
|
|
})
|
|
|
|
|
if err := g.Validator.ParseBody(c, req); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 更新用户信息
|
|
|
|
|
result, err := q.User.Where(
|
|
|
|
|
q.User.ID.Eq(int32(req.UserID)),
|
|
|
|
|
q.User.AdminID.IsNull(),
|
|
|
|
|
).UpdateColumnSimple(
|
|
|
|
|
q.User.AdminID.Value(authCtx.Admin.ID),
|
|
|
|
|
)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if result.RowsAffected == 0 {
|
|
|
|
|
return core.NewBizErr("用户已绑定管理员")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 返回结果
|
|
|
|
|
return c.SendStatus(fiber.StatusNoContent)
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-30 19:24:03 +08:00
|
|
|
// 更新用户
|
2025-04-29 18:48:14 +08:00
|
|
|
func UpdateUser(c *fiber.Ctx) error {
|
|
|
|
|
// 检查权限
|
2025-11-17 18:38:10 +08:00
|
|
|
authCtx, err := auth.GetAuthCtx(c).PermitUser()
|
2025-04-29 18:48:14 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解析请求参数
|
|
|
|
|
req := new(UpdateUserReq)
|
|
|
|
|
if err := c.BodyParser(req); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 更新用户信息
|
|
|
|
|
_, err = q.User.
|
2025-11-17 18:38:10 +08:00
|
|
|
Where(q.User.ID.Eq(authCtx.User.ID)).
|
2025-04-29 18:48:14 +08:00
|
|
|
Updates(m.User{
|
2025-05-26 10:57:39 +08:00
|
|
|
Username: &req.Username,
|
|
|
|
|
Email: &req.Email,
|
|
|
|
|
ContactQQ: &req.ContactQQ,
|
|
|
|
|
ContactWechat: &req.ContactWechat,
|
2025-04-29 18:48:14 +08:00
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 返回结果
|
|
|
|
|
return c.SendStatus(fiber.StatusNoContent)
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-30 19:24:03 +08:00
|
|
|
type UpdateUserReq struct {
|
|
|
|
|
Username string `json:"username" validate:"omitempty,min=3,max=20"`
|
|
|
|
|
Email string `json:"email" validate:"omitempty,email"`
|
|
|
|
|
ContactQQ string `json:"contact_qq" validate:"omitempty,qq"`
|
|
|
|
|
ContactWechat string `json:"contact_wechat" validate:"omitempty,wechat"`
|
2025-04-29 18:48:14 +08:00
|
|
|
}
|
|
|
|
|
|
2025-12-30 19:24:03 +08:00
|
|
|
// 更新账号信息
|
2025-04-29 18:48:14 +08:00
|
|
|
func UpdateAccount(c *fiber.Ctx) error {
|
|
|
|
|
// 检查权限
|
2025-11-17 18:38:10 +08:00
|
|
|
authCtx, err := auth.GetAuthCtx(c).PermitUser()
|
2025-04-29 18:48:14 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解析请求参数
|
|
|
|
|
req := new(UpdateAccountReq)
|
|
|
|
|
if err := c.BodyParser(req); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 更新用户信息
|
|
|
|
|
_, err = q.User.
|
2025-11-17 18:38:10 +08:00
|
|
|
Where(q.User.ID.Eq(authCtx.User.ID)).
|
2025-04-29 18:48:14 +08:00
|
|
|
Updates(m.User{
|
2025-05-26 10:57:39 +08:00
|
|
|
Username: &req.Username,
|
|
|
|
|
Password: &req.Password,
|
2025-04-29 18:48:14 +08:00
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 返回结果
|
|
|
|
|
return c.SendStatus(fiber.StatusNoContent)
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-30 19:24:03 +08:00
|
|
|
type UpdateAccountReq struct {
|
|
|
|
|
Username string `json:"username" validate:"omitempty,min=3,max=20"`
|
|
|
|
|
Password string `json:"password" validate:"omitempty,min=6,max=20"`
|
2025-04-29 18:48:14 +08:00
|
|
|
}
|
|
|
|
|
|
2025-12-30 19:24:03 +08:00
|
|
|
// 更新账号密码
|
2025-04-29 18:48:14 +08:00
|
|
|
func UpdatePassword(c *fiber.Ctx) error {
|
|
|
|
|
// 检查权限
|
2025-11-17 18:38:10 +08:00
|
|
|
authCtx, err := auth.GetAuthCtx(c).PermitUser()
|
2025-04-29 18:48:14 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解析请求参数
|
|
|
|
|
req := new(UpdatePasswordReq)
|
|
|
|
|
if err := c.BodyParser(req); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-27 16:28:28 +08:00
|
|
|
// 验证手机号
|
|
|
|
|
if req.Phone != authCtx.User.Phone {
|
|
|
|
|
return fiber.NewError(fiber.StatusBadRequest, "手机号码不正确")
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-29 18:48:14 +08:00
|
|
|
// 验证手机令牌
|
2026-02-27 16:28:28 +08:00
|
|
|
if req.Code == "" {
|
2025-05-15 10:24:02 +08:00
|
|
|
return fiber.NewError(fiber.StatusBadRequest, "手机号码和验证码不能为空")
|
2025-04-29 18:48:14 +08:00
|
|
|
}
|
|
|
|
|
err = s.Verifier.VerifySms(c.Context(), req.Phone, req.Code)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 更新密码
|
|
|
|
|
newHash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, err = q.User.
|
2025-11-17 18:38:10 +08:00
|
|
|
Where(q.User.ID.Eq(authCtx.User.ID)).
|
2025-04-29 18:48:14 +08:00
|
|
|
UpdateColumn(q.User.Password, newHash)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 返回结果
|
|
|
|
|
return c.SendStatus(fiber.StatusNoContent)
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-30 19:24:03 +08:00
|
|
|
type UpdatePasswordReq struct {
|
|
|
|
|
Phone string `json:"phone"`
|
|
|
|
|
Code string `json:"code"`
|
|
|
|
|
Password string `json:"password"`
|
|
|
|
|
}
|