Files
excel-api/handlers/workbook.go

206 lines
5.4 KiB
Go
Raw Permalink Normal View History

2026-06-26 14:31:24 +08:00
// Package handlers 实现API请求处理器
// 包含工作簿Excel文档的增删改查操作
// 工作簿通过 documents 表存储元数据workbooks 表存储Excel特化数据
package handlers
import (
"excel-api/models"
"excel-api/utils"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
// GetWorkbooks 获取工作簿列表
// 支持分页查询通过JOIN关联文档表获取完整信息
// 请求方式: GET
// 路径: /api/workbooks
// 查询参数: page(页码默认1), pageSize(每页条数默认20)
func GetWorkbooks(c *gin.Context) {
// 解析分页参数
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "20"))
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 20
}
var workbooks []models.Workbook
var total int64
// 查询总数(关联文档表)
models.DB.Model(&models.Workbook{}).Joins("JOIN documents ON documents.id = workbooks.document_id").Count(&total)
// 分页查询工作簿列表,预加载关联的工作表
result := models.DB.
Joins("JOIN documents ON documents.id = workbooks.document_id").
Preload("Sheets").
Offset((page - 1) * pageSize).Limit(pageSize).
Order("documents.created_at DESC").
Find(&workbooks)
if result.Error != nil {
utils.Error(c, 500, "查询工作簿列表失败")
return
}
utils.SuccessPage(c, workbooks, total, page, pageSize)
}
// CreateWorkbook 创建新工作簿
// 同时创建对应的文档记录和默认工作表
// 请求方式: POST
// 路径: /api/workbooks
// 请求体: { "title": "文档标题", "description": "描述" }
func CreateWorkbook(c *gin.Context) {
var req struct {
Title string `json:"title" binding:"required"` // 文档标题,必填
Description string `json:"description"` // 文档描述,可选
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.Error(c, 400, "参数错误: "+err.Error())
return
}
// 创建文档记录excel类型
document := models.Document{
Type: "excel",
Title: req.Title,
Description: req.Description,
CreatorID: 1, // 前期默认用户ID
Status: 1,
}
result := models.DB.Create(&document)
if result.Error != nil {
utils.Error(c, 500, "创建文档失败")
return
}
// 创建工作簿记录
workbook := models.Workbook{
DocumentID: document.ID,
}
result = models.DB.Create(&workbook)
if result.Error != nil {
utils.Error(c, 500, "创建工作簿失败")
return
}
// 为新工作簿创建默认工作表
defaultSheet := models.Sheet{
WorkbookID: workbook.ID,
Name: "Sheet1",
Index: 0,
ColCount: 26,
RowCount: 100,
}
models.DB.Create(&defaultSheet)
// 返回完整信息
workbook.Document = document
utils.SuccessWithMessage(c, "创建工作簿成功", workbook)
}
// GetWorkbook 获取工作簿详情
// 请求方式: GET
// 路径: /api/workbooks/:id
// 路径参数: id - 工作簿ID
func GetWorkbook(c *gin.Context) {
id := c.Param("id")
var workbook models.Workbook
// 查询工作簿并预加载关联的工作表和文档
result := models.DB.Preload("Sheets").Preload("Document").First(&workbook, id)
if result.Error != nil {
utils.Error(c, 404, "工作簿不存在")
return
}
utils.Success(c, workbook)
}
// UpdateWorkbook 更新工作簿信息
// 更新关联的文档表信息
// 请求方式: PUT
// 路径: /api/workbooks/:id
// 路径参数: id - 工作簿ID
// 请求体: { "title": "新标题", "description": "新描述" }
func UpdateWorkbook(c *gin.Context) {
id := c.Param("id")
var workbook models.Workbook
// 查找要更新的工作簿
result := models.DB.First(&workbook, id)
if result.Error != nil {
utils.Error(c, 404, "工作簿不存在")
return
}
var req struct {
Title string `json:"title"` // 文档标题
Description string `json:"description"` // 文档描述
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.Error(c, 400, "参数错误: "+err.Error())
return
}
// 更新关联的文档表
var document models.Document
if err := models.DB.First(&document, workbook.DocumentID).Error; err == nil {
if req.Title != "" {
document.Title = req.Title
}
document.Description = req.Description
models.DB.Save(&document)
}
utils.SuccessWithMessage(c, "更新工作簿成功", workbook)
}
// DeleteWorkbook 删除工作簿(软删除)
// 同时删除关联的文档、工作表和单元格
// 请求方式: DELETE
// 路径: /api/workbooks/:id
// 路径参数: id - 工作簿ID
func DeleteWorkbook(c *gin.Context) {
id := c.Param("id")
var workbook models.Workbook
// 查找要删除的工作簿
result := models.DB.First(&workbook, id)
if result.Error != nil {
utils.Error(c, 404, "工作簿不存在")
return
}
// 获取关联的工作表IDs
var sheetIDs []uint
models.DB.Model(&models.Sheet{}).Where("workbook_id = ?", id).Pluck("id", &sheetIDs)
// 软删除单元格
if len(sheetIDs) > 0 {
models.DB.Where("sheet_id IN ?", sheetIDs).Delete(&models.Cell{})
}
// 软删除工作表
models.DB.Where("workbook_id = ?", id).Delete(&models.Sheet{})
// 软删除工作簿
models.DB.Delete(&workbook)
// 软删除关联的文档
models.DB.Delete(&models.Document{}, workbook.DocumentID)
utils.SuccessWithMessage(c, "删除工作簿成功", nil)
}
// HandleOptions 处理OPTIONS预检请求
// 用于CORS跨域请求的预检
func HandleOptions(c *gin.Context) {
c.Status(http.StatusNoContent)
}