Files
server/app/http/controllers/admin/department_controller.go
2026-01-16 15:49:34 +08:00

228 lines
6.6 KiB
Go

package admin
import (
"github.com/goravel/framework/contracts/http"
apperrors "goravel/app/errors"
"goravel/app/http/helpers"
adminrequests "goravel/app/http/requests/admin"
"goravel/app/http/response"
"goravel/app/models"
"goravel/app/services"
)
type DepartmentController struct {
treeService services.TreeService
departmentService services.DepartmentService
}
func NewDepartmentController() *DepartmentController {
treeService := services.NewTreeServiceImpl()
return &DepartmentController{
treeService: treeService,
departmentService: services.NewDepartmentServiceImpl(treeService),
}
}
// findDepartmentByID 根据ID查找部门,如果不存在则返回错误响应
func (r *DepartmentController) findDepartmentByID(ctx http.Context, id uint) (*models.Department, http.Response) {
department, err := r.departmentService.GetByID(id)
if err != nil {
return nil, response.Error(ctx, http.StatusNotFound, apperrors.ErrDepartmentNotFound.Code)
}
return department, nil
}
// buildFilters 构建查询过滤器
func (r *DepartmentController) buildFilters(ctx http.Context) services.DepartmentFilters {
name := ctx.Request().Query("name", "")
status := ctx.Request().Query("status", "")
// 使用辅助函数自动转换时区
startTime := helpers.GetTimeQueryParam(ctx, "start_time")
endTime := helpers.GetTimeQueryParam(ctx, "end_time")
orderBy := ctx.Request().Query("order_by", "")
return services.DepartmentFilters{
Name: name,
Status: status,
StartTime: startTime,
EndTime: endTime,
OrderBy: orderBy,
}
}
// Index 部门列表(树形结构)
func (r *DepartmentController) Index(ctx http.Context) http.Response {
name := ctx.Request().Query("name", "")
status := ctx.Request().Query("status", "")
// 使用辅助函数自动转换时区
startTime := helpers.GetTimeQueryParam(ctx, "start_time")
endTime := helpers.GetTimeQueryParam(ctx, "end_time")
// 如果有搜索条件,返回扁平列表;否则返回树形结构
if name != "" || status != "" || startTime != "" || endTime != "" {
filters := r.buildFilters(ctx)
// 搜索时获取所有匹配的记录,不限制分页
departments, _, err := r.departmentService.GetList(filters, 1, 10000)
if err != nil {
return response.Error(ctx, http.StatusInternalServerError, apperrors.ErrQueryFailed.Code)
}
return response.Success(ctx, http.Json{
"list": departments,
})
}
// 无搜索条件时返回树形结构
departments, err := r.treeService.BuildDepartmentTree(0)
if err != nil {
return response.Error(ctx, http.StatusInternalServerError, apperrors.ErrQueryFailed.Code)
}
return response.Success(ctx, http.Json{
"list": departments,
})
}
// Show 部门详情
func (r *DepartmentController) Show(ctx http.Context) http.Response {
id := helpers.GetUintRoute(ctx, "id")
department, resp := r.findDepartmentByID(ctx, id)
if resp != nil {
return resp
}
return response.Success(ctx, http.Json{
"department": *department,
})
}
// Store 创建部门
func (r *DepartmentController) Store(ctx http.Context) http.Response {
// 使用请求验证
var departmentCreate adminrequests.DepartmentCreate
errors, err := ctx.Request().ValidateRequest(&departmentCreate)
if err != nil {
return response.Error(ctx, http.StatusBadRequest, err.Error())
}
if errors != nil {
return response.ValidationError(ctx, http.StatusBadRequest, "validation_failed", errors.All())
}
department, err := r.departmentService.Create(
departmentCreate.ParentID,
departmentCreate.Name,
departmentCreate.Code,
departmentCreate.Leader,
departmentCreate.Phone,
departmentCreate.Email,
departmentCreate.Remark,
departmentCreate.Status,
departmentCreate.Sort,
)
if err != nil {
return response.ErrorWithLog(ctx, "department", err, map[string]any{
"name": departmentCreate.Name,
})
}
return response.Success(ctx, http.Json{
"department": department,
})
}
// Update 更新部门
func (r *DepartmentController) Update(ctx http.Context) http.Response {
id := helpers.GetUintRoute(ctx, "id")
department, resp := r.findDepartmentByID(ctx, id)
if resp != nil {
return resp
}
// 使用请求验证
var departmentUpdate adminrequests.DepartmentUpdate
errors, err := ctx.Request().ValidateRequest(&departmentUpdate)
if err != nil {
return response.Error(ctx, http.StatusBadRequest, err.Error())
}
if errors != nil {
return response.ValidationError(ctx, http.StatusBadRequest, "validation_failed", errors.All())
}
// 使用 All() 方法检查字段是否存在
allInputs := ctx.Request().All()
if _, exists := allInputs["name"]; exists {
department.Name = departmentUpdate.Name
}
if _, exists := allInputs["parent_id"]; exists {
department.ParentID = departmentUpdate.ParentID
}
if _, exists := allInputs["code"]; exists {
department.Code = departmentUpdate.Code
}
if _, exists := allInputs["leader"]; exists {
department.Leader = departmentUpdate.Leader
}
if _, exists := allInputs["phone"]; exists {
department.Phone = departmentUpdate.Phone
}
if _, exists := allInputs["email"]; exists {
department.Email = departmentUpdate.Email
}
if _, exists := allInputs["status"]; exists {
department.Status = departmentUpdate.Status
}
if _, exists := allInputs["sort"]; exists {
department.Sort = departmentUpdate.Sort
}
if _, exists := allInputs["remark"]; exists {
department.Remark = departmentUpdate.Remark
}
if err := r.departmentService.Update(department); err != nil {
return response.ErrorWithLog(ctx, "department", err, map[string]any{
"department_id": department.ID,
})
}
return response.Success(ctx, http.Json{
"department": *department,
})
}
// Destroy 删除部门
func (r *DepartmentController) Destroy(ctx http.Context) http.Response {
id := helpers.GetUintRoute(ctx, "id")
department, resp := r.findDepartmentByID(ctx, id)
if resp != nil {
return resp
}
// 检查是否有子部门
hasChildren, err := r.treeService.HasDepartmentChildren(id)
if err != nil {
return response.Error(ctx, http.StatusInternalServerError, apperrors.ErrQueryFailed.Code)
}
if hasChildren {
return response.Error(ctx, http.StatusBadRequest, apperrors.ErrDepartmentHasChildren.Code)
}
// 检查是否有管理员
hasAdmins, err := r.departmentService.HasAdmins(id)
if err != nil {
return response.Error(ctx, http.StatusInternalServerError, apperrors.ErrQueryFailed.Code)
}
if hasAdmins {
return response.Error(ctx, http.StatusBadRequest, apperrors.ErrDepartmentHasAdmins.Code)
}
if err := r.departmentService.Delete(department); err != nil {
return response.ErrorWithLog(ctx, "department", err, map[string]any{
"department_id": department.ID,
})
}
return response.Success(ctx)
}