package category import ( "fmt" "net/http" "strconv" "strings" "management/internal/db/model/dto" db "management/internal/db/sqlc" "management/internal/pkg/convertor" "management/internal/router/manage/util" categoryservice "management/internal/service/category" "management/internal/tpl" "github.com/google/uuid" "github.com/jackc/pgx/v5/pgtype" ) type CategoryHandler struct{} func NewCategoryHandler() *CategoryHandler { return &CategoryHandler{} } func (h *CategoryHandler) List(w http.ResponseWriter, r *http.Request) { tpl.HTML(w, r, "category/list.tmpl", nil) } func (h *CategoryHandler) PostList(w http.ResponseWriter, r *http.Request) { var q dto.SearchDto q.SearchStatus = convertor.ConvertInt(r.PostFormValue("status"), 9999) q.SearchParentID = convertor.ConvertInt(r.PostFormValue("parentId"), 0) q.SearchName = r.PostFormValue("name") q.SearchID = convertor.ConvertInt[int64](r.PostFormValue("id"), 0) q.Page = convertor.ConvertInt(r.PostFormValue("page"), 1) q.Rows = convertor.ConvertInt(r.PostFormValue("rows"), 10) res, count, err := categoryservice.ListCategoriesCondition(r.Context(), q) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } data := tpl.ResponseList{ Code: 0, Message: "ok", Count: count, Data: res, } tpl.JSON(w, data) } func (h *CategoryHandler) Add(w http.ResponseWriter, r *http.Request) { tpl.HTML(w, r, "category/edit.tmpl", map[string]any{ "Item": &db.Category{Sort: 6666}, }) } func (h *CategoryHandler) AddChildren(w http.ResponseWriter, r *http.Request) { vars := r.URL.Query() parentID := util.DefaultInt(vars, "parentID", 0) vm := &db.Category{ParentID: int32(parentID), Sort: 6666} tpl.HTML(w, r, "category/edit.tmpl", map[string]any{ "Item": vm, }) } func (h *CategoryHandler) Edit(w http.ResponseWriter, r *http.Request) { vars := r.URL.Query() id := util.DefaultInt(vars, "id", 0) vm := &db.Category{Sort: 6666} if id > 0 { ctx := r.Context() vm, _ = db.Engine.GetCategory(ctx, int32(id)) } tpl.HTML(w, r, "category/edit.tmpl", map[string]any{ "Item": vm, }) } func (h *CategoryHandler) Save(w http.ResponseWriter, r *http.Request) { id := util.ConvertInt(r.PostFormValue("ID"), 0) parentID := util.ConvertInt(r.PostFormValue("ParentID"), 0) name := r.PostFormValue("Name") icon := r.PostFormValue("File") if len(icon) > 0 && !strings.HasPrefix(icon, "/") { icon = "/" + icon } description := r.PostFormValue("Description") letter := r.PostFormValue("Letter") if len(letter) == 0 { letter = uuid.New().String() } sort := util.ConvertInt(r.PostFormValue("Sort"), 6666) status := util.ConvertInt(r.PostFormValue("Status"), 9999) ctx := r.Context() var parent *db.Category if parentID > 0 { var err error parent, err = db.Engine.GetCategory(ctx, int32(parentID)) if err != nil { tpl.JSON(w, tpl.Response{Success: false, Message: "父级节点错误"}) return } } path := fmt.Sprintf("%s,%d,", parent.ParentPath, parent.ID) path = strings.ReplaceAll(path, ",,", ",") if id == 0 { arg := &db.CreateCategoryParams{ Name: name, Icon: icon, Description: description, Letter: letter, ParentID: int32(parentID), ParentPath: path, Status: int16(status), Sort: int32(sort), } _, err := db.Engine.CreateCategory(ctx, arg) if err != nil { if db.IsUniqueViolation(err) { tpl.JSON(w, tpl.Response{Success: false, Message: "名称已存在"}) return } tpl.JSON(w, tpl.Response{Success: false, Message: err.Error()}) return } tpl.JSON(w, tpl.Response{Success: true, Message: "添加成功"}) } else { arg := &db.UpdateCategoryParams{ ID: int32(id), Name: pgtype.Text{ String: name, Valid: true, }, Icon: pgtype.Text{ String: icon, Valid: len(icon) > 0, }, Description: pgtype.Text{ String: description, Valid: len(description) > 0, }, Letter: pgtype.Text{ String: letter, Valid: len(letter) > 0, }, ParentID: pgtype.Int4{ Int32: int32(parentID), Valid: true, }, ParentPath: pgtype.Text{ String: path, Valid: true, }, Sort: pgtype.Int4{ Int32: int32(sort), Valid: true, }, Status: pgtype.Int2{ Int16: int16(status), Valid: true, }, } _, err := db.Engine.UpdateCategory(ctx, arg) if err != nil { tpl.JSON(w, tpl.Response{Success: false, Message: err.Error()}) return } tpl.JSON(w, tpl.Response{Success: true, Message: "更新成功"}) } } func (h *CategoryHandler) DTree(w http.ResponseWriter, r *http.Request) { ctx := r.Context() vars := r.URL.Query() id := util.DefaultInt(vars, "id", 0) res, err := categoryservice.DTreeCategory(ctx, int32(id)) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } rsp := tpl.ResponseDtree{ Status: tpl.ResponseDtreeStatus{ Code: 200, Message: "OK", }, Data: res, } tpl.JSON(w, rsp) } func (h *CategoryHandler) XmSelect(w http.ResponseWriter, r *http.Request) { letter := r.URL.Query().Get("letter") ctx := r.Context() if len(letter) > 0 { all, err := categoryservice.ListByLetter(ctx, letter) if err != nil { tpl.JSONERR(w, err.Error()) return } var res []*dto.XmSelectStrDto for _, v := range all { res = append(res, &dto.XmSelectStrDto{ Name: v.Name, Value: strconv.FormatInt(int64(v.ID), 10), }) } tpl.JSON(w, res) return } res, err := categoryservice.XmSelectCategory(ctx, 0) if err != nil { tpl.JSONERR(w, err.Error()) return } tpl.JSON(w, res) } func (h *CategoryHandler) Refresh(w http.ResponseWriter, r *http.Request) { ctx := r.Context() err := categoryservice.RefreshCategory(ctx) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } tpl.JSON(w, tpl.Response{Success: true, Message: "刷新成功"}) } func (h *CategoryHandler) RebuildParentPath(w http.ResponseWriter, r *http.Request) { ctx := r.Context() err := db.Engine.CategoryRebuildPath(ctx) if err != nil { tpl.JSON(w, tpl.Response{Success: false, Message: err.Error()}) return } tpl.JSON(w, tpl.Response{Success: true, Message: "重建成功"}) }