docs(website): 添加简记memo产品原型和UI设计规范文档
- 新增「简记memo」一体化小程序产品原型设计文档 - 新增简记memo完整版UI视觉设计规范和界面细节 - 添加IDEA项目配置文件.gitignore - 创建404页面HTML文件,包含响应式布局和错误提示 - 添加关于页面HTML文件,展示品牌介绍和团队信息 - 实现AES加解密工具函数,支持请求体加密 - 添加用户协议页面基础框架
This commit is contained in:
@@ -0,0 +1,266 @@
|
||||
// 复盘接口(仅 KPT 法)
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"simple-memo/global"
|
||||
"simple-memo/models"
|
||||
"simple-memo/utils"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// -------------------------- 1. 定义 Handler 接口 --------------------------
|
||||
type ReviewHandler interface {
|
||||
SaveReview(c *gin.Context) // 保存复盘
|
||||
GetReview(c *gin.Context) // 获取单日复盘
|
||||
ReviewList(c *gin.Context) // 获取复盘列表
|
||||
DeleteReview(c *gin.Context) // 删除复盘
|
||||
}
|
||||
|
||||
// -------------------------- 2. 实现结构体 --------------------------
|
||||
type reviewHandler struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewReviewHandler() ReviewHandler {
|
||||
return &reviewHandler{
|
||||
db: global.DB,
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------- 3. 请求结构体 --------------------------
|
||||
|
||||
// SaveReviewReq 保存复盘请求
|
||||
type SaveReviewReq struct {
|
||||
Date string `json:"date" binding:"required"` // YYYY-MM-DD
|
||||
Kpt SaveReviewKPTDto `json:"kpt"`
|
||||
}
|
||||
type SaveReviewKPTDto struct {
|
||||
Keep string `json:"keep"`
|
||||
Problem string `json:"problem"`
|
||||
Try string `json:"try"`
|
||||
}
|
||||
|
||||
// GetReviewReq 获取单日复盘请求
|
||||
type GetReviewReq struct {
|
||||
Date string `json:"date" binding:"required"`
|
||||
}
|
||||
|
||||
// ReviewListReq 获取复盘列表请求
|
||||
type ReviewListReq struct {
|
||||
StartDate string `json:"start_date"`
|
||||
EndDate string `json:"end_date"`
|
||||
Keyword string `json:"keyword"`
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
}
|
||||
|
||||
// DeleteReviewReq 删除复盘请求
|
||||
type DeleteReviewReq struct {
|
||||
ID uint `json:"id" binding:"required"`
|
||||
}
|
||||
|
||||
// -------------------------- 4. 接口实现 --------------------------
|
||||
|
||||
// SaveReview 保存复盘
|
||||
func (h *reviewHandler) SaveReview(c *gin.Context) {
|
||||
userID := c.GetUint("userID")
|
||||
var req SaveReviewReq
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.Fail(c, "参数解析失败")
|
||||
return
|
||||
}
|
||||
|
||||
var review models.Review
|
||||
isNewRecord := false
|
||||
|
||||
err := h.db.Where("user_id = ? AND date = ?", userID, req.Date).First(&review).Error
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
review = models.Review{
|
||||
UserID: userID,
|
||||
Date: req.Date,
|
||||
Keep: utils.FilterSensitive(req.Kpt.Keep),
|
||||
Problem: utils.FilterSensitive(req.Kpt.Problem),
|
||||
Try: utils.FilterSensitive(req.Kpt.Try),
|
||||
}
|
||||
isNewRecord = true
|
||||
} else if err != nil {
|
||||
utils.Fail(c, "查询失败")
|
||||
return
|
||||
} else {
|
||||
review.Keep = utils.FilterSensitive(req.Kpt.Keep)
|
||||
review.Problem = utils.FilterSensitive(req.Kpt.Problem)
|
||||
review.Try = utils.FilterSensitive(req.Kpt.Try)
|
||||
}
|
||||
|
||||
if isNewRecord {
|
||||
if err := h.db.Create(&review).Error; err != nil {
|
||||
utils.Fail(c, "保存失败")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if err := h.db.Save(&review).Error; err != nil {
|
||||
utils.Fail(c, "保存失败")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var growthResult any
|
||||
debugMode := os.Getenv("DEBUG_MODE")
|
||||
if isNewRecord {
|
||||
today := time.Now().Format("2006-01-02")
|
||||
if req.Date == today {
|
||||
if debugMode == "true" {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
levelUp := rand.Intn(10) < 2
|
||||
hasAchievement := rand.Intn(10) < 3
|
||||
growthResult = MockGrowthRewards(levelUp, hasAchievement)
|
||||
} else {
|
||||
growthHandler := NewGrowthHandler()
|
||||
growthResult = growthHandler.AddExpInternal(userID, "review", fmt.Sprintf("%d", review.ID), nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
utils.Ok(c, gin.H{
|
||||
"success": true,
|
||||
"growth": growthResult,
|
||||
"review": review,
|
||||
"isNewRecord": isNewRecord,
|
||||
})
|
||||
}
|
||||
|
||||
// GetReview 获取单日复盘
|
||||
func (h *reviewHandler) GetReview(c *gin.Context) {
|
||||
userID := c.GetUint("userID")
|
||||
var req GetReviewReq
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.Fail(c, "参数解析失败")
|
||||
return
|
||||
}
|
||||
|
||||
var review models.Review
|
||||
err := h.db.Where("user_id = ? AND date = ?", userID, req.Date).First(&review).Error
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
utils.Ok(c, nil)
|
||||
return
|
||||
} else if err != nil {
|
||||
utils.Fail(c, "查询失败")
|
||||
return
|
||||
}
|
||||
|
||||
utils.Ok(c, review)
|
||||
}
|
||||
|
||||
// ReviewList 获取复盘列表
|
||||
func (h *reviewHandler) ReviewList(c *gin.Context) {
|
||||
userID := c.GetUint("userID")
|
||||
var req ReviewListReq
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.Fail(c, "参数解析失败")
|
||||
return
|
||||
}
|
||||
|
||||
if req.Page <= 0 {
|
||||
req.Page = 1
|
||||
}
|
||||
if req.PageSize <= 0 {
|
||||
req.PageSize = 20
|
||||
}
|
||||
|
||||
db := h.db.Model(&models.Review{}).Where("user_id = ?", userID)
|
||||
|
||||
if req.StartDate != "" && req.EndDate != "" {
|
||||
db = db.Where("date BETWEEN ? AND ?", req.StartDate, req.EndDate)
|
||||
} else if req.StartDate != "" {
|
||||
db = db.Where("date >= ?", req.StartDate)
|
||||
} else if req.EndDate != "" {
|
||||
db = db.Where("date <= ?", req.EndDate)
|
||||
}
|
||||
|
||||
if req.Keyword != "" {
|
||||
keyword := "%" + req.Keyword + "%"
|
||||
db = db.Where("(keep LIKE ? OR problem LIKE ? OR try LIKE ?)", keyword, keyword, keyword)
|
||||
}
|
||||
|
||||
var total int64
|
||||
db.Count(&total)
|
||||
|
||||
var list []models.Review
|
||||
offset := (req.Page - 1) * req.PageSize
|
||||
err := db.Order("date DESC").Offset(offset).Limit(req.PageSize).Find(&list).Error
|
||||
if err != nil {
|
||||
utils.Fail(c, "查询失败")
|
||||
return
|
||||
}
|
||||
|
||||
type ReviewListItem struct {
|
||||
ID uint `json:"id"`
|
||||
Date string `json:"date"`
|
||||
Summary string `json:"summary"`
|
||||
}
|
||||
|
||||
result := make([]ReviewListItem, len(list))
|
||||
for i, r := range list {
|
||||
summary := r.Keep
|
||||
if len(summary) > 50 {
|
||||
summary = summary[:50] + "..."
|
||||
}
|
||||
result[i] = ReviewListItem{
|
||||
ID: r.ID,
|
||||
Date: r.Date,
|
||||
Summary: summary,
|
||||
}
|
||||
}
|
||||
|
||||
utils.Ok(c, gin.H{
|
||||
"list": result,
|
||||
"total": total,
|
||||
"page": req.Page,
|
||||
"pageSize": req.PageSize,
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteReview 删除复盘
|
||||
func (h *reviewHandler) DeleteReview(c *gin.Context) {
|
||||
userID := c.GetUint("userID")
|
||||
var req DeleteReviewReq
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.Fail(c, "参数解析失败")
|
||||
return
|
||||
}
|
||||
|
||||
var review models.Review
|
||||
err := h.db.Where("id = ? AND user_id = ?", req.ID, userID).First(&review).Error
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
utils.Fail(c, "复盘不存在")
|
||||
return
|
||||
} else if err != nil {
|
||||
utils.Fail(c, "查询失败")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.db.Delete(&review).Error; err != nil {
|
||||
utils.Fail(c, "删除失败")
|
||||
return
|
||||
}
|
||||
|
||||
growthHandler := NewGrowthHandler()
|
||||
today := time.Now().Format("2006-01-02")
|
||||
deducted := growthHandler.DeductExpInternal(userID, "review", fmt.Sprintf("%d", req.ID), today)
|
||||
|
||||
utils.Ok(c, gin.H{
|
||||
"success": true,
|
||||
"deducted_exp": deducted,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user