good-news/main.go

269 lines
6.9 KiB
Go
Raw Normal View History

2025-04-03 02:23:49 +00:00
package main
import (
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
"github.com/gin-gonic/gin"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"github.com/google/uuid"
"goodnews/models"
"goodnews/services"
)
// 全局数据库连接
var db *gorm.DB
func main() {
// 初始化数据库
var err error
db, err = gorm.Open(sqlite.Open("goodnews.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// 自动迁移数据库
db.AutoMigrate(&models.GoodNews{})
// 初始化Gin路由
r := gin.Default()
// 设置静态文件服务
r.Static("/uploads", "./uploads")
// 设置页面路由
r.StaticFile("/", "./templates/index.html")
r.StaticFile("/manage", "./templates/manage.html")
// API路由组
api := r.Group("/api")
{
api.GET("/news", getGoodNewsList)
api.PUT("/news/:id", updateGoodNews)
api.DELETE("/news/:id", deleteGoodNews)
api.POST("/upload", handleUploadAndCreate)
api.GET("/offices", getOfficesList)
}
// 启动服务
r.Run(":8080")
}
// 获取喜报列表
func getGoodNewsList(c *gin.Context) {
var goodNewsList []models.GoodNews
2025-04-07 03:18:38 +00:00
result := db.Order("created_at desc").Find(&goodNewsList)
2025-04-03 02:23:49 +00:00
if result.Error != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()})
return
}
// 处理每条记录添加图片URL并设置Office字段
for i := range goodNewsList {
// 将ImagePath转换为可访问的URL
goodNewsList[i].ImageURL = "/" + goodNewsList[i].ImagePath
// 确保Office字段与Representative字段一致
goodNewsList[i].Office = goodNewsList[i].Representative
}
c.JSON(http.StatusOK, goodNewsList)
}
// 获取代表处列表
func getOfficesList(c *gin.Context) {
var offices []string
result := db.Model(&models.GoodNews{}).Distinct().Pluck("representative", &offices)
if result.Error != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()})
return
}
c.JSON(http.StatusOK, offices)
}
// 处理文件上传并创建喜报
func handleUploadAndCreate(c *gin.Context) {
// 获取上传的图片
file, err := c.FormFile("file")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请选择要上传的图片文件"})
return
}
// 验证文件类型
ext := filepath.Ext(file.Filename)
allowedExts := map[string]bool{".jpg": true, ".jpeg": true, ".png": true}
if !allowedExts[strings.ToLower(ext)] {
c.JSON(http.StatusBadRequest, gin.H{"error": "只支持jpg、jpeg和png格式的图片"})
return
}
// 验证文件大小限制为10MB
if file.Size > 10<<20 { // 10 MB
c.JSON(http.StatusBadRequest, gin.H{"error": "图片大小不能超过10MB"})
return
}
// 生成唯一的文件名
newFileName := uuid.New().String() + ext
uploadDir := filepath.Join(".", "uploads")
filePath := filepath.Join(uploadDir, newFileName)
// 确保上传目录存在
if err := os.MkdirAll(uploadDir, 0755); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("创建上传目录失败: %v", err)})
return
}
// 保存图片
if err := c.SaveUploadedFile(file, filePath); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("图片保存失败: %v", err)})
return
}
// 创建OCR服务
ocrService, err := services.NewOCRService()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "OCR服务初始化失败"})
return
}
defer ocrService.Close()
// 提取图片信息
projectName, points, representative, err := ocrService.ExtractInfo(filePath)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("图片识别失败: %v", err)})
return
}
fmt.Println("OCR识别信息:", projectName, points, representative)
// 创建喜报记录
2025-04-07 03:18:38 +00:00
var pointValue int
if len(points) > 0 {
pointValue = points[0]
}
2025-04-03 02:23:49 +00:00
goodNews := models.GoodNews{
ProjectName: projectName,
2025-04-07 03:18:38 +00:00
Points: pointValue,
2025-04-03 02:23:49 +00:00
Representative: representative,
ImagePath: filePath,
}
result := db.Create(&goodNews)
if result.Error != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()})
return
}
// 重新获取记录以确保包含ID
db.First(&goodNews, goodNews.ID)
goodNews.ImageURL = "/" + goodNews.ImagePath
c.JSON(http.StatusOK, goodNews)
}
// 更新喜报
func updateGoodNews(c *gin.Context) {
var goodNews models.GoodNews
if err := db.First(&goodNews, c.Param("id")).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "记录不存在"})
return
}
if err := c.ShouldBindJSON(&goodNews); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
db.Save(&goodNews)
c.JSON(http.StatusOK, goodNews)
}
// 删除喜报
func deleteGoodNews(c *gin.Context) {
var goodNews models.GoodNews
if err := db.First(&goodNews, c.Param("id")).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "记录不存在"})
return
}
db.Delete(&goodNews)
c.JSON(http.StatusOK, gin.H{"message": "删除成功"})
}
// 处理文件上传
func handleFileUpload(c *gin.Context) {
// 获取上传的文件
file, err := c.FormFile("file")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请选择要上传的文件"})
return
}
// 验证文件类型
ext := filepath.Ext(file.Filename)
allowedExts := map[string]bool{".jpg": true, ".jpeg": true, ".png": true}
if !allowedExts[strings.ToLower(ext)] {
c.JSON(http.StatusBadRequest, gin.H{"error": "只支持jpg、jpeg和png格式的图片"})
return
}
// 生成唯一的文件名
newFileName := uuid.New().String() + ext
uploadDir := filepath.Join(".", "uploads")
filePath := filepath.Join(uploadDir, newFileName)
// 确保上传目录存在
if err := os.MkdirAll(uploadDir, 0755); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("创建上传目录失败: %v", err)})
return
}
// 保存图片
if err := c.SaveUploadedFile(file, filePath); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("图片保存失败: %v", err)})
return
}
// 创建OCR服务
ocrService, err := services.NewOCRService()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "OCR服务初始化失败"})
return
}
defer ocrService.Close()
// 提取图片信息
projectName, points, representative, err := ocrService.ExtractInfo(filePath)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("图片识别失败: %v", err)})
return
}
// 创建喜报记录
2025-04-07 03:18:38 +00:00
var pointValue int
if len(points) > 0 {
pointValue = points[0]
}
2025-04-03 02:23:49 +00:00
goodNews := models.GoodNews{
ProjectName: projectName,
2025-04-07 03:18:38 +00:00
Points: pointValue,
2025-04-03 02:23:49 +00:00
Representative: representative,
ImagePath: filePath,
}
result := db.Create(&goodNews)
if result.Error != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()})
return
}
// 重新获取记录以确保包含ID
db.First(&goodNews, goodNews.ID)
goodNews.ImageURL = "/" + goodNews.ImagePath
c.JSON(http.StatusOK, goodNews)
}