259 lines
6.7 KiB
Go
259 lines
6.7 KiB
Go
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
|
||
result := db.Find(&goodNewsList)
|
||
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)
|
||
// 创建喜报记录
|
||
goodNews := models.GoodNews{
|
||
ProjectName: projectName,
|
||
Points: points,
|
||
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
|
||
}
|
||
|
||
// 创建喜报记录
|
||
goodNews := models.GoodNews{
|
||
ProjectName: projectName,
|
||
Points: points,
|
||
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)
|
||
} |