Files
memora/memora-api/internal/handler/word.go

141 lines
3.3 KiB
Go

package handler
import (
"fmt"
"net/http"
"strconv"
"strings"
"memora-api/internal/model"
"memora-api/internal/service"
"github.com/gin-gonic/gin"
)
type WordHandler struct {
wordService *service.WordService
}
func NewWordHandler(wordService *service.WordService) *WordHandler {
return &WordHandler{wordService: wordService}
}
// 添加单词(记忆模式)
func (h *WordHandler) AddWord(c *gin.Context) {
var req model.AddWordRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 调用有道API查询
youdaoResp, err := h.wordService.QueryWord(req.Word)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询失败: " + err.Error()})
return
}
if youdaoResp.ErrorCode != "0" && youdaoResp.ErrorCode != "" {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("有道API错误: %s", youdaoResp.ErrorCode)})
return
}
// 保存到数据库
word, err := h.wordService.SaveWord(req.Word, youdaoResp)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "保存失败: " + err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "单词添加成功",
"data": word,
})
}
// 获取复习单词列表
func (h *WordHandler) GetReviewWords(c *gin.Context) {
mode := c.DefaultQuery("mode", "spelling")
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))
words, err := h.wordService.GetReviewWords(mode, limit)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": words})
}
// 提交复习答案
func (h *WordHandler) SubmitReview(c *gin.Context) {
var req model.ReviewAnswerRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
result, err := h.wordService.SubmitReviewAnswer(req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": result})
}
// 获取所有单词
func (h *WordHandler) GetWords(c *gin.Context) {
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20"))
offset, _ := strconv.Atoi(c.DefaultQuery("offset", "0"))
words, total, err := h.wordService.GetAllWords(limit, offset)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"data": words,
"total": total,
})
}
// 获取统计信息
func (h *WordHandler) GetStatistics(c *gin.Context) {
stats, err := h.wordService.GetStatistics()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": stats})
}
// 获取音频文件
func (h *WordHandler) GetAudio(c *gin.Context) {
word := c.Query("word")
audioType := c.DefaultQuery("type", "uk")
if word == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "缺少word参数"})
return
}
// very small sanitization
word = strings.TrimSpace(word)
if word == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "word为空"})
return
}
for _, r := range word {
if !(r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z') {
c.JSON(http.StatusBadRequest, gin.H{"error": "word包含非法字符"})
return
}
}
filename := word + "_" + audioType + ".mp3"
path := "./audio/" + filename
c.File(path)
}