package controllers import ( "encoding/json" "io" "server/middleware" "server/models" "server/pkg/jwtutil" "strconv" "strings" "time" "github.com/beego/beego/v2/client/orm" beego "github.com/beego/beego/v2/server/web" ) type AppNotebookController struct { beego.Controller } func (c *AppNotebookController) appNotebookClaims() (*jwtutil.Claims, error) { auth := c.Ctx.Request.Header.Get("Authorization") if auth == "" { return nil, orm.ErrNoRows } parts := strings.SplitN(auth, " ", 2) if len(parts) != 2 || parts[0] != "Bearer" { return nil, orm.ErrNoRows } claims, err := jwtutil.ParseToken(parts[1]) if err != nil { return nil, err } if claims.UserType != "backend" && claims.UserType != "app" && claims.UserType != "platform" { return nil, orm.ErrNoRows } return claims, nil } func (c *AppNotebookController) nbJsonErr(httpStatus, bizCode int, msg string) { c.Ctx.Output.SetStatus(httpStatus) c.Data["json"] = map[string]interface{}{"code": bizCode, "msg": msg} _ = c.ServeJSON() } func (c *AppNotebookController) nbOk(data interface{}) { c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": data} _ = c.ServeJSON() } // GetList GET /app/notebook/list func (c *AppNotebookController) GetList() { claims, err := c.appNotebookClaims() if err != nil { c.nbJsonErr(401, 401, "未登录或无权限") return } keyword := strings.TrimSpace(c.GetString("keyword")) qs := models.Orm.QueryTable(new(models.BackendNotebook)). Filter("is_deleted", 0). Filter("user_id", claims.UserID) if keyword != "" { qs = qs.Filter("title__icontains", keyword) } var list []models.BackendNotebook _, err = qs.OrderBy("-pinned", "-update_time").All(&list) if err != nil && err != orm.ErrNoRows { c.nbJsonErr(500, 500, "查询失败") return } if list == nil { list = []models.BackendNotebook{} } type noteItem struct { ID uint64 `json:"id"` Title string `json:"title"` Content string `json:"content"` Pinned bool `json:"pinned"` CreatedAt string `json:"created_at"` UpdatedAt string `json:"updated_at"` } result := make([]noteItem, 0, len(list)) for _, n := range list { item := noteItem{ ID: n.ID, Title: n.Title, Content: n.Content, Pinned: n.Pinned == 1, } item.CreatedAt = n.CreateTime.Format("2006-01-02 15:04:05") if n.UpdateTime != nil { item.UpdatedAt = n.UpdateTime.Format("2006-01-02 15:04:05") } else { item.UpdatedAt = item.CreatedAt } result = append(result, item) } c.nbOk(map[string]interface{}{ "list": result, "total": len(result), }) } // GetDetail GET /app/notebook/:id func (c *AppNotebookController) GetDetail() { claims, err := c.appNotebookClaims() if err != nil { c.nbJsonErr(401, 401, "未登录或无权限") return } id, err := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if err != nil || id == 0 { c.nbJsonErr(400, 400, "无效ID") return } var note models.BackendNotebook err = models.Orm.QueryTable(new(models.BackendNotebook)). Filter("id", id). Filter("is_deleted", 0). Filter("user_id", claims.UserID). One(¬e) if err != nil { c.nbJsonErr(404, 404, "笔记不存在") return } createdAt := note.CreateTime.Format("2006-01-02 15:04:05") updatedAt := createdAt if note.UpdateTime != nil { updatedAt = note.UpdateTime.Format("2006-01-02 15:04:05") } c.nbOk(map[string]interface{}{ "id": note.ID, "title": note.Title, "content": note.Content, "pinned": note.Pinned == 1, "created_at": createdAt, "updated_at": updatedAt, }) } // Create POST /app/notebook func (c *AppNotebookController) Create() { claims, err := c.appNotebookClaims() if err != nil { c.nbJsonErr(401, 401, "未登录或无权限") return } raw, err := io.ReadAll(c.Ctx.Request.Body) if err != nil { c.nbJsonErr(400, 400, "参数错误") return } var payload struct { Title string `json:"title"` Content string `json:"content"` Pinned bool `json:"pinned"` } if err := json.Unmarshal(raw, &payload); err != nil { c.nbJsonErr(400, 400, "参数错误") return } title := strings.TrimSpace(payload.Title) if title == "" { title = "无标题" } userID := uint64(claims.UserID) pinned := int8(0) if payload.Pinned { pinned = 1 } note := &models.BackendNotebook{ Tid: claims.TenantId, Title: title, Content: payload.Content, Pinned: pinned, UserID: &userID, UserName: &claims.Username, IsDeleted: 0, } id, err := models.Orm.Insert(note) if err != nil { c.nbJsonErr(500, 500, "创建失败") return } note.ID = uint64(id) c.nbOk(map[string]interface{}{ "id": note.ID, "title": note.Title, "content": note.Content, "pinned": note.Pinned == 1, }) } // Update PUT /app/notebook/:id func (c *AppNotebookController) Update() { claims, err := c.appNotebookClaims() if err != nil { c.nbJsonErr(401, 401, "未登录或无权限") return } id, err := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if err != nil || id == 0 { c.nbJsonErr(400, 400, "无效ID") return } raw, err := io.ReadAll(c.Ctx.Request.Body) if err != nil { c.nbJsonErr(400, 400, "参数错误") return } var payload struct { Title string `json:"title"` Content string `json:"content"` Pinned *bool `json:"pinned"` } if err := json.Unmarshal(raw, &payload); err != nil { c.nbJsonErr(400, 400, "参数错误") return } var note models.BackendNotebook err = models.Orm.QueryTable(new(models.BackendNotebook)). Filter("id", id). Filter("is_deleted", 0). Filter("user_id", claims.UserID). One(¬e) if err != nil { c.nbJsonErr(404, 404, "笔记不存在") return } updateFields := map[string]interface{}{ "update_time": time.Now(), } if payload.Title != "" { updateFields["title"] = strings.TrimSpace(payload.Title) } updateFields["content"] = payload.Content if payload.Pinned != nil { if *payload.Pinned { updateFields["pinned"] = int8(1) } else { updateFields["pinned"] = int8(0) } } _, err = models.Orm.QueryTable(new(models.BackendNotebook)). Filter("id", id). Update(updateFields) if err != nil { c.nbJsonErr(500, 500, "更新失败") return } now := time.Now() createdAt := note.CreateTime.Format("2006-01-02 15:04:05") c.nbOk(map[string]interface{}{ "id": note.ID, "title": updateFields["title"], "content": payload.Content, "pinned": payload.Pinned != nil && *payload.Pinned, "created_at": createdAt, "updated_at": now.Format("2006-01-02 15:04:05"), }) } // Delete DELETE /app/notebook/:id func (c *AppNotebookController) Delete() { claims, err := c.appNotebookClaims() if err != nil { c.nbJsonErr(401, 401, "未登录或无权限") return } id, err := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if err != nil || id == 0 { c.nbJsonErr(400, 400, "无效ID") return } var note models.BackendNotebook err = models.Orm.QueryTable(new(models.BackendNotebook)). Filter("id", id). Filter("is_deleted", 0). Filter("user_id", claims.UserID). One(¬e) if err != nil { c.nbJsonErr(404, 404, "笔记不存在") return } now := time.Now() _, err = models.Orm.QueryTable(new(models.BackendNotebook)). Filter("id", id). Update(map[string]interface{}{ "is_deleted": 1, "delete_time": now, }) if err != nil { c.nbJsonErr(500, 500, "删除失败") return } middleware.WriteDeleteLog(uint64(claims.UserID), claims.TenantId, "notebook", note.Title) c.nbOk(nil) } // TogglePin POST /app/notebook/:id/togglePin func (c *AppNotebookController) TogglePin() { claims, err := c.appNotebookClaims() if err != nil { c.nbJsonErr(401, 401, "未登录或无权限") return } id, err := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if err != nil || id == 0 { c.nbJsonErr(400, 400, "无效ID") return } var note models.BackendNotebook err = models.Orm.QueryTable(new(models.BackendNotebook)). Filter("id", id). Filter("is_deleted", 0). Filter("user_id", claims.UserID). One(¬e) if err != nil { c.nbJsonErr(404, 404, "笔记不存在") return } var newPinned int8 if note.Pinned == 1 { newPinned = 0 } else { newPinned = 1 } now := time.Now() _, err = models.Orm.QueryTable(new(models.BackendNotebook)). Filter("id", id). Update(map[string]interface{}{ "pinned": newPinned, "update_time": now, }) if err != nil { c.nbJsonErr(500, 500, "操作失败") return } c.nbOk(map[string]interface{}{ "pinned": newPinned == 1, }) }