feat: 限制用户单日提问次数
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package plant
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sundynix-go/global"
|
||||
"sundynix-go/model/commom/response"
|
||||
"sundynix-go/utils/auth"
|
||||
@@ -24,7 +25,19 @@ func (a *AiChatApi) ChatStreamPlant(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// SSE Headers(微信小程序通过 enableChunked: true 配合实现打字机效果)
|
||||
userId := auth.GetUserId(c)
|
||||
|
||||
// ── 每日用量检查 ──
|
||||
cfg, cfgErr := sysAiConfigService.GetActiveAiConfig()
|
||||
if cfgErr == nil && cfg.DailyQueryLimit > 0 {
|
||||
todayCount, _ := chatHistoryService.GetTodayCount(userId)
|
||||
if todayCount >= int64(cfg.DailyQueryLimit) {
|
||||
response.FailWithMsg(fmt.Sprintf("今日问答次数已达上限(%d次),明天再来吧", cfg.DailyQueryLimit), c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// SSE Headers
|
||||
w := c.Writer
|
||||
header := w.Header()
|
||||
header.Set("Content-Type", "text/event-stream")
|
||||
@@ -46,14 +59,12 @@ func (a *AiChatApi) ChatStreamPlant(c *gin.Context) {
|
||||
_, _ = w.WriteString("data: [ERROR]" + err.Error() + "\n\n")
|
||||
w.Flush()
|
||||
} else {
|
||||
// 流结束标志
|
||||
_, _ = w.WriteString("data: [DONE]\n\n")
|
||||
w.Flush()
|
||||
}
|
||||
|
||||
// 异步保存问答历史
|
||||
if fullAnswer != "" {
|
||||
userId := auth.GetUserId(c)
|
||||
go func() {
|
||||
if saveErr := chatHistoryService.SaveHistory(userId, query, fullAnswer); saveErr != nil {
|
||||
global.Logger.Error("Save chat history failed", zap.Error(saveErr))
|
||||
@@ -138,6 +149,34 @@ func (a *AiChatApi) ClearChatHistory(c *gin.Context) {
|
||||
response.OkWithMsg("已清空", c)
|
||||
}
|
||||
|
||||
// GetChatQuota 获取当前用户今日剩余问答额度
|
||||
// @Tags Plant-AiChat
|
||||
// @Router /plant/chat/quota [get]
|
||||
func (a *AiChatApi) GetChatQuota(c *gin.Context) {
|
||||
userId := auth.GetUserId(c)
|
||||
todayCount, _ := chatHistoryService.GetTodayCount(userId)
|
||||
|
||||
limit := 0 // 0 = unlimited
|
||||
cfg, err := sysAiConfigService.GetActiveAiConfig()
|
||||
if err == nil && cfg.DailyQueryLimit > 0 {
|
||||
limit = cfg.DailyQueryLimit
|
||||
}
|
||||
|
||||
remaining := -1 // -1 means unlimited
|
||||
if limit > 0 {
|
||||
remaining = limit - int(todayCount)
|
||||
if remaining < 0 {
|
||||
remaining = 0
|
||||
}
|
||||
}
|
||||
|
||||
response.OkWithData(map[string]interface{}{
|
||||
"used": todayCount,
|
||||
"limit": limit,
|
||||
"remaining": remaining,
|
||||
}, c)
|
||||
}
|
||||
|
||||
func parseInt(s string) int {
|
||||
n := 0
|
||||
for _, c := range s {
|
||||
|
||||
Reference in New Issue
Block a user