spark-server/internal/transport/http/handler/admin/client.go
DESKTOP-L8OUL9F\gfl0034 082f420347 feat: 意见反馈支持登录与游客分流
可选 Bearer 写入 auth_type/uid,游客必填 contact;Admin 与 popadmin 可按类型筛选。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-24 16:24:47 +08:00

125 lines
3.0 KiB
Go

package adminhandler
import (
"net/http"
"strconv"
"strings"
"github.com/gin-gonic/gin"
"spark-server/internal/module/client/entity"
clientlogic "spark-server/internal/module/client/logic"
)
// ClientHandler serves popadmin legal / subscription / feedback ops.
type ClientHandler struct {
svc *clientlogic.Service
}
func NewClient(svc *clientlogic.Service) *ClientHandler {
return &ClientHandler{svc: svc}
}
func (h *ClientHandler) ready(c *gin.Context) bool {
if h == nil || h.svc == nil || !h.svc.Ready() {
Fail(c, http.StatusServiceUnavailable, "client 服务未就绪")
return false
}
return true
}
func (h *ClientHandler) GetLegal(c *gin.Context) {
if !h.ready(c) {
return
}
out, err := h.svc.LegalAgreements(c.Request.Context())
if err != nil {
Fail(c, http.StatusInternalServerError, err.Error())
return
}
OK(c, out)
}
func (h *ClientHandler) PutLegal(c *gin.Context) {
if !h.ready(c) {
return
}
var body entity.LegalDocument
if err := c.ShouldBindJSON(&body); err != nil {
Fail(c, http.StatusBadRequest, "无效 JSON")
return
}
if err := h.svc.UpsertLegalAdmin(c.Request.Context(), &body); err != nil {
Fail(c, http.StatusBadRequest, err.Error())
return
}
OKMsg(c, "已保存", body)
}
func (h *ClientHandler) ListPlans(c *gin.Context) {
if !h.ready(c) {
return
}
lang := c.Query("lang")
list, err := h.svc.ListPlansAdmin(c.Request.Context(), lang)
if err != nil {
Fail(c, http.StatusInternalServerError, err.Error())
return
}
OK(c, gin.H{"items": list})
}
func (h *ClientHandler) PutPlan(c *gin.Context) {
if !h.ready(c) {
return
}
var body entity.SubscriptionPlan
if err := c.ShouldBindJSON(&body); err != nil {
Fail(c, http.StatusBadRequest, "无效 JSON")
return
}
if err := h.svc.UpsertPlanAdmin(c.Request.Context(), &body); err != nil {
Fail(c, http.StatusBadRequest, err.Error())
return
}
OKMsg(c, "已保存", body)
}
func (h *ClientHandler) ListFeedback(c *gin.Context) {
if !h.ready(c) {
return
}
page, _ := strconv.Atoi(c.DefaultQuery("page", "0"))
size, _ := strconv.Atoi(c.DefaultQuery("size", "50"))
authType := strings.TrimSpace(c.Query("auth_type"))
list, total, err := h.svc.ListFeedbackAdmin(c.Request.Context(), page, size, authType)
if err != nil {
Fail(c, http.StatusInternalServerError, err.Error())
return
}
OK(c, gin.H{"list": list, "total": total, "page": page, "size": size, "auth_type": authType})
}
func (h *ClientHandler) PatchFeedback(c *gin.Context) {
if !h.ready(c) {
return
}
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil || id <= 0 {
Fail(c, http.StatusBadRequest, "无效 id")
return
}
var body struct {
Status string `json:"status"`
}
if err := c.ShouldBindJSON(&body); err != nil || body.Status == "" {
Fail(c, http.StatusBadRequest, "status 必填")
return
}
if err := h.svc.UpdateFeedbackStatus(c.Request.Context(), id, body.Status); err != nil {
Fail(c, http.StatusBadRequest, err.Error())
return
}
OKMsg(c, "已更新", gin.H{"id": id, "status": body.Status})
}