Files
soul-yongping/soul-api/internal/handler/admin_user_rules.go
2026-03-24 01:22:50 +08:00

214 lines
6.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handler
import (
"encoding/json"
"net/http"
"strconv"
"soul-api/internal/database"
"soul-api/internal/model"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// MiniprogramUserRules GET /api/miniprogram/user-rules小程序端只返回启用的规则
func MiniprogramUserRules(c *gin.Context) {
db := database.DB()
var rules []model.UserRule
if err := db.Where("enabled = ?", true).Order("sort ASC, id ASC").Find(&rules).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
out := make([]gin.H, 0, len(rules))
for _, r := range rules {
out = append(out, gin.H{"id": r.ID, "title": r.Title, "description": r.Description, "trigger": r.Trigger, "sort": r.Sort})
}
c.JSON(http.StatusOK, gin.H{"success": true, "rules": out})
}
// DBUserRulesList GET /api/db/user-rules
func DBUserRulesList(c *gin.Context) {
db := database.DB()
var rules []model.UserRule
if err := db.Order("sort ASC, id ASC").Find(&rules).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"success": true, "rules": rules})
}
// MiniprogramUserRulesGet GET /api/miniprogram/user-rules?userId=xxx
// 返回启用的规则,并标记当前用户已完成的规则
func MiniprogramUserRulesGet(c *gin.Context) {
db := database.DB()
var rules []model.UserRule
if err := db.Where("enabled = ?", true).Order("sort ASC, id ASC").Find(&rules).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
userId := c.Query("userId")
completedSet := make(map[uint]bool)
if userId != "" {
var completions []model.UserRuleCompletion
db.Where("user_id = ?", userId).Find(&completions)
for _, comp := range completions {
completedSet[comp.RuleID] = true
}
}
out := make([]gin.H, 0, len(rules))
for _, r := range rules {
out = append(out, gin.H{
"id": r.ID, "title": r.Title, "description": r.Description,
"trigger": r.Trigger, "sort": r.Sort, "completed": completedSet[r.ID],
})
}
c.JSON(http.StatusOK, gin.H{"success": true, "rules": out})
}
// MiniprogramUserRuleComplete POST /api/miniprogram/user-rules/complete
func MiniprogramUserRuleComplete(c *gin.Context) {
var body struct {
UserID string `json:"userId" binding:"required"`
RuleID uint `json:"ruleId" binding:"required"`
}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "参数错误"})
return
}
db := database.DB()
comp := model.UserRuleCompletion{UserID: body.UserID, RuleID: body.RuleID}
result := db.Where("user_id = ? AND rule_id = ?", body.UserID, body.RuleID).FirstOrCreate(&comp)
if result.Error != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": result.Error.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"success": true, "alreadyCompleted": result.RowsAffected == 0})
}
// DBUserRulesAction POST/PUT/DELETE /api/db/user-rules
func DBUserRulesAction(c *gin.Context) {
db := database.DB()
switch c.Request.Method {
case http.MethodPost:
var body struct {
Title string `json:"title" binding:"required"`
Description string `json:"description"`
Trigger string `json:"trigger"`
TriggerConditions interface{} `json:"triggerConditions"`
ActionType string `json:"actionType"`
ActionConfig interface{} `json:"actionConfig"`
Sort int `json:"sort"`
Enabled *bool `json:"enabled"`
}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "参数错误"})
return
}
enabled := true
if body.Enabled != nil {
enabled = *body.Enabled
}
rule := model.UserRule{
Title: trimSpace(body.Title),
Description: body.Description,
Trigger: trimSpace(body.Trigger),
ActionType: trimSpace(body.ActionType),
Sort: body.Sort,
Enabled: enabled,
}
if body.TriggerConditions != nil {
if b, err := json.Marshal(body.TriggerConditions); err == nil {
rule.TriggerConditions = b
}
}
if body.ActionConfig != nil {
if b, err := json.Marshal(body.ActionConfig); err == nil {
rule.ActionConfig = b
}
}
if err := db.Create(&rule).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"success": true, "rule": rule})
case http.MethodPut:
var body struct {
ID uint `json:"id" binding:"required"`
Title string `json:"title"`
Description string `json:"description"`
Trigger string `json:"trigger"`
TriggerConditions interface{} `json:"triggerConditions"`
ActionType string `json:"actionType"`
ActionConfig interface{} `json:"actionConfig"`
Sort *int `json:"sort"`
Enabled *bool `json:"enabled"`
}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "参数错误"})
return
}
var rule model.UserRule
if err := db.First(&rule, body.ID).Error; err != nil {
if err == gorm.ErrRecordNotFound {
c.JSON(http.StatusNotFound, gin.H{"success": false, "error": "规则不存在"})
return
}
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
updates := make(map[string]interface{})
if body.Title != "" {
updates["title"] = trimSpace(body.Title)
}
updates["description"] = body.Description
updates["trigger"] = trimSpace(body.Trigger)
updates["action_type"] = trimSpace(body.ActionType)
if body.TriggerConditions != nil {
if b, err := json.Marshal(body.TriggerConditions); err == nil {
updates["trigger_conditions"] = string(b)
}
}
if body.ActionConfig != nil {
if b, err := json.Marshal(body.ActionConfig); err == nil {
updates["action_config"] = string(b)
}
}
if body.Sort != nil {
updates["sort"] = *body.Sort
}
if body.Enabled != nil {
updates["enabled"] = *body.Enabled
}
if err := db.Model(&rule).Updates(updates).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
var updated model.UserRule
_ = db.First(&updated, body.ID)
c.JSON(http.StatusOK, gin.H{"success": true, "rule": updated})
case http.MethodDelete:
idStr := c.Query("id")
if idStr == "" {
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "缺少 id"})
return
}
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "id 无效"})
return
}
if err := db.Delete(&model.UserRule{}, uint(id)).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"success": true})
default:
c.JSON(http.StatusMethodNotAllowed, gin.H{"success": false, "error": "方法不支持"})
}
}