Files
excel-api/handlers/workbook.go
2026-06-26 14:31:24 +08:00

206 lines
5.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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)
}