package controllers import ( "errors" "hr_receiver/config" "hr_receiver/models" "net/http" "strconv" "strings" "github.com/gin-gonic/gin" "gorm.io/gorm" ) type KindergartenAdminController struct { DB *gorm.DB } type kindergartenPayload struct { Address string `json:"address"` Name string `json:"name"` RegionID uint32 `json:"regionId"` } func NewKindergartenAdminController() *KindergartenAdminController { return &KindergartenAdminController{DB: config.DB} } // @Summary 获取幼儿园列表 // @Description 查询幼儿园列表,支持按名称/地址模糊搜索 // @Tags 幼儿园管理 // @Produce json // @Param keyword query string false "关键词(名称/地址模糊搜索)" // @Security BearerAuth // @Success 200 {object} SwagAPIResponse "查询成功" // @Router /admin/kindergartens [get] func (kc *KindergartenAdminController) List(c *gin.Context) { var items []models.Kindergarten query := kc.DB.Model(&models.Kindergarten{}).Order("region_id ASC, id ASC") if keyword := strings.TrimSpace(c.Query("keyword")); keyword != "" { likeValue := "%" + keyword + "%" query = query.Where("name LIKE ? OR address LIKE ?", likeValue, likeValue) } if err := query.Find(&items).Error; err != nil { writeError(c, http.StatusInternalServerError, "failed to query kindergartens") return } writeSuccess(c, http.StatusOK, "query success", items) } // @Summary 创建幼儿园 // @Description 创建新的幼儿园记录 // @Tags 幼儿园管理 // @Accept json // @Produce json // @Param kindergarten body kindergartenPayload true "幼儿园信息" // @Security BearerAuth // @Success 201 {object} SwagAPIResponse "创建成功" // @Failure 400 {object} SwagAPIResponse "请求参数错误" // @Router /admin/kindergartens [post] func (kc *KindergartenAdminController) Create(c *gin.Context) { var payload kindergartenPayload if err := c.ShouldBindJSON(&payload); err != nil { writeError(c, http.StatusBadRequest, err.Error()) return } if err := validateKindergartenPayload(payload); err != nil { writeError(c, http.StatusBadRequest, err.Error()) return } record := models.Kindergarten{ Address: strings.TrimSpace(payload.Address), Name: strings.TrimSpace(payload.Name), RegionID: payload.RegionID, } if err := kc.DB.Create(&record).Error; err != nil { writeKindergartenDBError(c, err) return } writeSuccess(c, http.StatusCreated, "create success", record) } // @Summary 更新幼儿园信息 // @Description 更新指定幼儿园的名称、地址和区域 // @Tags 幼儿园管理 // @Accept json // @Produce json // @Param id path int true "幼儿园ID" // @Param kindergarten body kindergartenPayload true "更新信息" // @Security BearerAuth // @Success 200 {object} SwagAPIResponse "更新成功" // @Failure 400 {object} SwagAPIResponse "请求参数错误" // @Failure 404 {object} SwagAPIResponse "幼儿园不存在" // @Router /admin/kindergartens/{id} [put] func (kc *KindergartenAdminController) Update(c *gin.Context) { record, err := kc.findByID(c.Param("id")) if err != nil { respondKindergartenLookupError(c, err) return } var payload kindergartenPayload if err := c.ShouldBindJSON(&payload); err != nil { writeError(c, http.StatusBadRequest, err.Error()) return } if err := validateKindergartenPayload(payload); err != nil { writeError(c, http.StatusBadRequest, err.Error()) return } record.Name = strings.TrimSpace(payload.Name) record.Address = strings.TrimSpace(payload.Address) record.RegionID = payload.RegionID if err := kc.DB.Save(&record).Error; err != nil { writeKindergartenDBError(c, err) return } writeSuccess(c, http.StatusOK, "update success", record) } // @Summary 删除幼儿园 // @Description 删除指定幼儿园,如果被用户绑定则无法删除 // @Tags 幼儿园管理 // @Produce json // @Param id path int true "幼儿园ID" // @Security BearerAuth // @Success 200 {object} SwagAPIResponse "删除成功" // @Failure 404 {object} SwagAPIResponse "幼儿园不存在" // @Failure 409 {object} SwagAPIResponse "已绑定用户无法删除" // @Router /admin/kindergartens/{id} [delete] func (kc *KindergartenAdminController) Delete(c *gin.Context) { record, err := kc.findByID(c.Param("id")) if err != nil { respondKindergartenLookupError(c, err) return } var bindings int64 if err := kc.DB.Model(&models.UserRegionBinding{}).Where("region_id = ?", record.RegionID).Count(&bindings).Error; err != nil { writeError(c, http.StatusInternalServerError, "failed to check user bindings") return } if bindings > 0 { writeError(c, http.StatusConflict, "current kindergarten is bound to users") return } if err := kc.DB.Delete(&record).Error; err != nil { writeError(c, http.StatusInternalServerError, "failed to delete kindergarten") return } writeSuccess(c, http.StatusOK, "delete success", nil) } func (kc *KindergartenAdminController) findByID(id string) (models.Kindergarten, error) { var record models.Kindergarten numericID, err := strconv.ParseUint(strings.TrimSpace(id), 10, 64) if err != nil { return record, gorm.ErrRecordNotFound } if err := kc.DB.First(&record, numericID).Error; err != nil { return record, err } return record, nil } func validateKindergartenPayload(payload kindergartenPayload) error { if strings.TrimSpace(payload.Name) == "" { return errors.New("name is required") } if strings.TrimSpace(payload.Address) == "" { return errors.New("address is required") } if payload.RegionID == 0 { return errors.New("regionId is required") } return nil } func respondKindergartenLookupError(c *gin.Context, err error) { if errors.Is(err, gorm.ErrRecordNotFound) { writeError(c, http.StatusNotFound, "kindergarten not found") return } writeError(c, http.StatusInternalServerError, "failed to query kindergarten") } func writeKindergartenDBError(c *gin.Context, err error) { if strings.Contains(strings.ToLower(err.Error()), "unique") { writeError(c, http.StatusConflict, "regionId already has a kindergarten") return } writeError(c, http.StatusInternalServerError, "failed to persist kindergarten") }