初始化
This commit is contained in:
153
handlers/cell.go
Normal file
153
handlers/cell.go
Normal file
@@ -0,0 +1,153 @@
|
||||
// Package handlers 实现单元格相关的API请求处理器
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"excel-api/models"
|
||||
"excel-api/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// CellRequest 单元格更新请求结构体
|
||||
type CellRequest struct {
|
||||
Row int `json:"row" binding:"required"` // 行号(0-based),必填
|
||||
Col int `json:"col" binding:"required"` // 列号(0-based),必填
|
||||
CellType string `json:"cellType"` // 单元格类型
|
||||
Value string `json:"value"` // 文本值
|
||||
Formula string `json:"formula"` // 公式表达式
|
||||
FileURL string `json:"fileUrl"` // 文件URL
|
||||
FileName string `json:"fileName"` // 文件名
|
||||
FileSize int64 `json:"fileSize"` // 文件大小
|
||||
MimeType string `json:"mimeType"` // MIME类型
|
||||
}
|
||||
|
||||
// GetCells 获取工作表的单元格数据
|
||||
// 请求方式: GET
|
||||
// 路径: /api/sheets/:id/cells
|
||||
// 路径参数: id - 工作表ID
|
||||
// 查询参数: row(起始行), col(起始列), endRow(结束行), endCol(结束列)
|
||||
func GetCells(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
// 验证工作表是否存在
|
||||
var sheet models.Sheet
|
||||
if result := models.DB.First(&sheet, id); result.Error != nil {
|
||||
utils.Error(c, 404, "工作表不存在")
|
||||
return
|
||||
}
|
||||
|
||||
// 获取查询参数(可选范围查询)
|
||||
query := models.DB.Where("sheet_id = ?", id)
|
||||
|
||||
// 如果提供了范围参数,则按范围过滤
|
||||
if row := c.Query("row"); row != "" {
|
||||
query = query.Where("row >= ?", row)
|
||||
}
|
||||
if col := c.Query("col"); col != "" {
|
||||
query = query.Where("col >= ?", col)
|
||||
}
|
||||
if endRow := c.Query("endRow"); endRow != "" {
|
||||
query = query.Where("row <= ?", endRow)
|
||||
}
|
||||
if endCol := c.Query("endCol"); endCol != "" {
|
||||
query = query.Where("col <= ?", endCol)
|
||||
}
|
||||
|
||||
var cells []models.Cell
|
||||
result := query.Find(&cells)
|
||||
if result.Error != nil {
|
||||
utils.Error(c, 500, "查询单元格数据失败")
|
||||
return
|
||||
}
|
||||
|
||||
utils.Success(c, cells)
|
||||
}
|
||||
|
||||
// BatchUpdateCells 批量更新单元格数据
|
||||
// 请求方式: POST
|
||||
// 路径: /api/sheets/:id/cells
|
||||
// 路径参数: id - 工作表ID
|
||||
// 请求体: { "cells": [{ "row": 0, "col": 0, "value": "Hello" }, ...] }
|
||||
func BatchUpdateCells(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
// 验证工作表是否存在
|
||||
var sheet models.Sheet
|
||||
if result := models.DB.First(&sheet, id); result.Error != nil {
|
||||
utils.Error(c, 404, "工作表不存在")
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Cells []CellRequest `json:"cells" binding:"required"` // 单元格更新列表,必填
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.Error(c, 400, "参数错误: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 使用事务批量更新单元格
|
||||
tx := models.DB.Begin()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
for _, cellReq := range req.Cells {
|
||||
// 查找已存在的单元格
|
||||
var cell models.Cell
|
||||
result := tx.Where("sheet_id = ? AND row = ? AND col = ?", id, cellReq.Row, cellReq.Col).First(&cell)
|
||||
|
||||
if result.Error != nil {
|
||||
// 单元格不存在,创建新记录
|
||||
cell = models.Cell{
|
||||
SheetID: sheet.ID,
|
||||
Row: cellReq.Row,
|
||||
Col: cellReq.Col,
|
||||
CellType: cellReq.CellType,
|
||||
Value: cellReq.Value,
|
||||
Formula: cellReq.Formula,
|
||||
FileURL: cellReq.FileURL,
|
||||
FileName: cellReq.FileName,
|
||||
FileSize: cellReq.FileSize,
|
||||
MimeType: cellReq.MimeType,
|
||||
}
|
||||
// 设置默认类型
|
||||
if cell.CellType == "" {
|
||||
cell.CellType = "text"
|
||||
}
|
||||
if err := tx.Create(&cell).Error; err != nil {
|
||||
tx.Rollback()
|
||||
utils.Error(c, 500, "创建单元格失败")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// 单元格已存在,更新字段
|
||||
if cellReq.CellType != "" {
|
||||
cell.CellType = cellReq.CellType
|
||||
}
|
||||
cell.Value = cellReq.Value
|
||||
cell.Formula = cellReq.Formula
|
||||
cell.FileURL = cellReq.FileURL
|
||||
cell.FileName = cellReq.FileName
|
||||
cell.FileSize = cellReq.FileSize
|
||||
cell.MimeType = cellReq.MimeType
|
||||
|
||||
if err := tx.Save(&cell).Error; err != nil {
|
||||
tx.Rollback()
|
||||
utils.Error(c, 500, "更新单元格失败")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 提交事务
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
utils.Error(c, 500, "提交事务失败")
|
||||
return
|
||||
}
|
||||
|
||||
utils.SuccessWithMessage(c, "批量更新单元格成功", nil)
|
||||
}
|
||||
174
handlers/sheet.go
Normal file
174
handlers/sheet.go
Normal file
@@ -0,0 +1,174 @@
|
||||
// Package handlers 实现工作表相关的API请求处理器
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"excel-api/models"
|
||||
"excel-api/utils"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// GetSheets 获取工作簿下的工作表列表
|
||||
// 请求方式: GET
|
||||
// 路径: /api/workbooks/:wid/sheets
|
||||
// 路径参数: wid - 工作簿ID
|
||||
func GetSheets(c *gin.Context) {
|
||||
wid := c.Param("wid")
|
||||
|
||||
// 验证工作簿是否存在
|
||||
var workbook models.Workbook
|
||||
if result := models.DB.First(&workbook, wid); result.Error != nil {
|
||||
utils.Error(c, 404, "工作簿不存在")
|
||||
return
|
||||
}
|
||||
|
||||
var sheets []models.Sheet
|
||||
// 查询该工作簿下的所有工作表,按索引排序
|
||||
result := models.DB.Where("workbook_id = ?", wid).Order("index ASC").Find(&sheets)
|
||||
if result.Error != nil {
|
||||
utils.Error(c, 500, "查询工作表列表失败")
|
||||
return
|
||||
}
|
||||
|
||||
utils.Success(c, sheets)
|
||||
}
|
||||
|
||||
// CreateSheet 在工作簿下创建新工作表
|
||||
// 请求方式: POST
|
||||
// 路径: /api/workbooks/:wid/sheets
|
||||
// 路径参数: wid - 工作簿ID
|
||||
// 请求体: { "name": "工作表名称" }
|
||||
func CreateSheet(c *gin.Context) {
|
||||
wid := c.Param("wid")
|
||||
|
||||
// 验证工作簿是否存在
|
||||
var workbook models.Workbook
|
||||
if result := models.DB.First(&workbook, wid); result.Error != nil {
|
||||
utils.Error(c, 404, "工作簿不存在")
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Name string `json:"name" binding:"required"` // 工作表名称,必填
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.Error(c, 400, "参数错误: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 获取当前工作簿下最大的排序索引
|
||||
var maxIndex int
|
||||
models.DB.Model(&models.Sheet{}).Where("workbook_id = ?", wid).Select("COALESCE(MAX(index), -1)").Scan(&maxIndex)
|
||||
|
||||
widNum, _ := strconv.Atoi(wid)
|
||||
sheet := models.Sheet{
|
||||
WorkbookID: uint(widNum),
|
||||
Name: req.Name,
|
||||
Index: maxIndex + 1,
|
||||
ColCount: 26,
|
||||
RowCount: 100,
|
||||
}
|
||||
|
||||
result := models.DB.Create(&sheet)
|
||||
if result.Error != nil {
|
||||
utils.Error(c, 500, "创建工作表失败")
|
||||
return
|
||||
}
|
||||
|
||||
utils.SuccessWithMessage(c, "创建工作表成功", sheet)
|
||||
}
|
||||
|
||||
// GetSheet 获取工作表详情
|
||||
// 请求方式: GET
|
||||
// 路径: /api/sheets/:id
|
||||
// 路径参数: id - 工作表ID
|
||||
func GetSheet(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var sheet models.Sheet
|
||||
|
||||
result := models.DB.First(&sheet, id)
|
||||
if result.Error != nil {
|
||||
utils.Error(c, 404, "工作表不存在")
|
||||
return
|
||||
}
|
||||
|
||||
utils.Success(c, sheet)
|
||||
}
|
||||
|
||||
// UpdateSheet 更新工作表信息
|
||||
// 请求方式: PUT
|
||||
// 路径: /api/sheets/:id
|
||||
// 路径参数: id - 工作表ID
|
||||
// 请求体: { "name": "新名称", "index": 0, "colCount": 26, "rowCount": 100 }
|
||||
func UpdateSheet(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var sheet models.Sheet
|
||||
|
||||
result := models.DB.First(&sheet, id)
|
||||
if result.Error != nil {
|
||||
utils.Error(c, 404, "工作表不存在")
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Name string `json:"name"` // 工作表名称
|
||||
Index int `json:"index"` // 排序索引
|
||||
ColCount int `json:"colCount"` // 列数量
|
||||
RowCount int `json:"rowCount"` // 行数量
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.Error(c, 400, "参数错误: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if req.Name != "" {
|
||||
sheet.Name = req.Name
|
||||
}
|
||||
if req.Index >= 0 {
|
||||
sheet.Index = req.Index
|
||||
}
|
||||
if req.ColCount > 0 {
|
||||
sheet.ColCount = req.ColCount
|
||||
}
|
||||
if req.RowCount > 0 {
|
||||
sheet.RowCount = req.RowCount
|
||||
}
|
||||
|
||||
result = models.DB.Save(&sheet)
|
||||
if result.Error != nil {
|
||||
utils.Error(c, 500, "更新工作表失败")
|
||||
return
|
||||
}
|
||||
|
||||
utils.SuccessWithMessage(c, "更新工作表成功", sheet)
|
||||
}
|
||||
|
||||
// DeleteSheet 删除工作表(软删除)
|
||||
// 请求方式: DELETE
|
||||
// 路径: /api/sheets/:id
|
||||
// 路径参数: id - 工作表ID
|
||||
func DeleteSheet(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var sheet models.Sheet
|
||||
|
||||
result := models.DB.First(&sheet, id)
|
||||
if result.Error != nil {
|
||||
utils.Error(c, 404, "工作表不存在")
|
||||
return
|
||||
}
|
||||
|
||||
// 软删除工作表及其关联的单元格
|
||||
result = models.DB.Delete(&sheet)
|
||||
if result.Error != nil {
|
||||
utils.Error(c, 500, "删除工作表失败")
|
||||
return
|
||||
}
|
||||
|
||||
// 同时删除关联的单元格
|
||||
models.DB.Where("sheet_id = ?", id).Delete(&models.Cell{})
|
||||
|
||||
utils.SuccessWithMessage(c, "删除工作表成功", nil)
|
||||
}
|
||||
130
handlers/upload.go
Normal file
130
handlers/upload.go
Normal file
@@ -0,0 +1,130 @@
|
||||
// Package handlers 实现文件上传相关的API请求处理器
|
||||
// 支持图片、视频、音频、文档等文件上传
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"excel-api/config"
|
||||
"excel-api/utils"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// allowedExtensions 允许上传的文件扩展名白名单
|
||||
var allowedExtensions = map[string]bool{
|
||||
// 图片格式
|
||||
".png": true, ".jpg": true, ".jpeg": true, ".gif": true, ".webp": true, ".svg": true,
|
||||
// 视频格式
|
||||
".mp4": true, ".webm": true, ".mov": true,
|
||||
// 音频格式
|
||||
".mp3": true, ".wav": true, ".ogg": true, ".flac": true,
|
||||
// 压缩包格式
|
||||
".zip": true, ".rar": true, ".7z": true, ".tar": true, ".gz": true,
|
||||
// 文档格式
|
||||
".pdf": true, ".doc": true, ".docx": true, ".xls": true, ".xlsx": true,
|
||||
".ppt": true, ".pptx": true, ".txt": true, ".csv": true,
|
||||
}
|
||||
|
||||
// DetectFileType 根据文件扩展名自动检测文件类型
|
||||
// 返回值: image/video/audio/archive/file
|
||||
func DetectFileType(filename string) string {
|
||||
ext := strings.ToLower(filepath.Ext(filename))
|
||||
switch ext {
|
||||
case ".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg":
|
||||
return "image"
|
||||
case ".mp4", ".webm", ".mov":
|
||||
return "video"
|
||||
case ".mp3", ".wav", ".ogg", ".flac":
|
||||
return "audio"
|
||||
case ".zip", ".rar", ".7z", ".tar", ".gz":
|
||||
return "archive"
|
||||
default:
|
||||
return "file"
|
||||
}
|
||||
}
|
||||
|
||||
// UploadResponse 文件上传响应结构体
|
||||
type UploadResponse struct {
|
||||
URL string `json:"url"` // 文件访问URL
|
||||
Name string `json:"name"` // 原始文件名
|
||||
Size int64 `json:"size"` // 文件大小(字节)
|
||||
MimeType string `json:"mimeType"` // 文件MIME类型
|
||||
FileType string `json:"fileType"` // 自动检测的文件类型
|
||||
}
|
||||
|
||||
// Upload 处理文件上传请求
|
||||
// 请求方式: POST
|
||||
// 路径: /api/upload
|
||||
// 请求体: multipart/form-data,字段名为 "file"
|
||||
func Upload(c *gin.Context) {
|
||||
// 获取上传的文件
|
||||
file, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
utils.Error(c, 400, "请选择要上传的文件")
|
||||
return
|
||||
}
|
||||
|
||||
// 验证文件扩展名
|
||||
ext := strings.ToLower(filepath.Ext(file.Filename))
|
||||
if !allowedExtensions[ext] {
|
||||
utils.Error(c, 400, "不支持的文件格式: "+ext)
|
||||
return
|
||||
}
|
||||
|
||||
// 限制文件大小(最大 100MB)
|
||||
const maxFileSize = 100 * 1024 * 1024
|
||||
if file.Size > maxFileSize {
|
||||
utils.Error(c, 400, "文件大小超过限制(最大100MB)")
|
||||
return
|
||||
}
|
||||
|
||||
// 确定存储路径
|
||||
storagePath := config.App.Storage.Local.Path
|
||||
if storagePath == "" {
|
||||
storagePath = "./uploads"
|
||||
}
|
||||
|
||||
// 按日期创建子目录:uploads/2024/01/
|
||||
dateDir := time.Now().Format("2006/01")
|
||||
uploadDir := filepath.Join(storagePath, dateDir)
|
||||
|
||||
// 创建存储目录(如果不存在)
|
||||
if err := os.MkdirAll(uploadDir, 0755); err != nil {
|
||||
utils.Error(c, 500, "创建上传目录失败")
|
||||
return
|
||||
}
|
||||
|
||||
// 生成唯一文件名:时间戳 + 随机数 + 原始扩展名
|
||||
filename := fmt.Sprintf("%d%s", time.Now().UnixNano(), ext)
|
||||
filePath := filepath.Join(uploadDir, filename)
|
||||
|
||||
// 保存文件到磁盘
|
||||
if err := c.SaveUploadedFile(file, filePath); err != nil {
|
||||
utils.Error(c, 500, "保存文件失败")
|
||||
return
|
||||
}
|
||||
|
||||
// 检测文件MIME类型
|
||||
mimeType := file.Header.Get("Content-Type")
|
||||
if mimeType == "" {
|
||||
mimeType = "application/octet-stream"
|
||||
}
|
||||
|
||||
// 自动检测文件类型
|
||||
fileType := DetectFileType(file.Filename)
|
||||
|
||||
// 返回文件访问URL(相对路径)
|
||||
url := fmt.Sprintf("/uploads/%s/%s", dateDir, filename)
|
||||
|
||||
utils.Success(c, UploadResponse{
|
||||
URL: url,
|
||||
Name: file.Filename,
|
||||
Size: file.Size,
|
||||
MimeType: mimeType,
|
||||
FileType: fileType,
|
||||
})
|
||||
}
|
||||
205
handlers/workbook.go
Normal file
205
handlers/workbook.go
Normal file
@@ -0,0 +1,205 @@
|
||||
// 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)
|
||||
}
|
||||
Reference in New Issue
Block a user