Files
smartmate/backend/services/tokenstore/sv/credit_dashboard.go
Losita 61db646805 Version: 0.9.80.dev.260506
后端:
1. LLM 独立服务与统一计费出口落地:新增 `cmd/llm`、`client/llm` 与 `services/llm/rpc`,补齐 BillingContext、CreditBalanceGuard、价格规则解析、stream usage 归集与 `credit.charge.requested` outbox 发布,active-scheduler / agent / course / memory / gateway fallback 全部改走 llm zrpc,不再各自本地初始化模型。
2. TokenStore 收口为 Credit 权威账本:新增 credit account / ledger / product / order / price-rule / reward-rule 能力与 Redis 快照缓存,扩展 tokenstore rpc/client 支撑余额快照、消耗看板、商品、订单、流水、价格规则和奖励规则,并接入 LLM charge 事件消费完成 Credit 扣费落账。
3. 计费旧链路下线与网关切口切换:`/token-store` 语义整体切到 `/credit-store`,agent chat 移除旧 TokenQuotaGuard,userauth 的 CheckTokenQuota / AdjustTokenUsage 改为废弃,聊天历史落库不再同步旧 token 额度账本,course 图片解析请求补 user_id 进入新计费口径。

前端:
4. 计划广场从 mock 数据切到真实接口:新增 forum api/types,首页支持真实列表、标签、搜索、防抖、点赞、导入和发布计划,详情页补齐帖子详情、评论树、回复和删除评论链路,同时补上“至少一个标签”的前后端约束与默认标签兜底。
5. 商店页切到 Credit 体系并重做展示:顶部改为余额 + Credit/Token 消耗看板,支持 24h/7d/30d/all 周期切换;套餐区展示原价与当前价;历史区改为当前用户 Credit 流水并支持查看更多,整体视觉和交互同步收口。

仓库:
6. 配置与本地启动体系补齐 llm / outbox 编排:`config.example.yaml` 增加 llm rpc 和统一 outbox service 配置,`dev-common.ps1` 把 llm 纳入多服务依赖并自动建 Kafka topic,`docker-compose.yml` 同步初始化 agent/task/memory/active-scheduler/notification/taskclass-forum/llm/token-store 全量 outbox topic。
2026-05-06 20:16:53 +08:00

87 lines
3.2 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 sv
import (
"context"
"strings"
"time"
tokenstoredao "github.com/LoveLosita/smartflow/backend/services/tokenstore/dao"
creditcontracts "github.com/LoveLosita/smartflow/backend/shared/contracts/creditstore"
"github.com/LoveLosita/smartflow/backend/shared/respond"
)
// GetCreditConsumptionDashboard 返回当前用户的 Credit 消耗看板。
//
// 职责边界:
// 1. 负责把前端周期参数归一化为 tokenstore 的统一时间窗口。
// 2. 只校验当前用户语义和周期合法性,真正的聚合查询下沉到 DAO。
// 3. 返回值只包含前端顶部看板需要的两个指标,不夹带商品、流水等其它信息。
func (s *Service) GetCreditConsumptionDashboard(ctx context.Context, req creditcontracts.GetCreditConsumptionDashboardRequest) (*creditcontracts.CreditConsumptionDashboardView, error) {
if err := s.Ready(); err != nil {
return nil, err
}
if req.ActorUserID == 0 {
return nil, respond.MissingParam
}
period, err := normalizeCreditConsumptionPeriod(req.Period)
if err != nil {
return nil, err
}
query := tokenstoredao.GetCreditConsumptionDashboardQuery{
UserID: req.ActorUserID,
CreatedFrom: resolveCreditConsumptionWindowStart(period, time.Now()),
}
aggregate, err := s.creditDAO.GetCreditConsumptionDashboard(ctx, query)
if err != nil {
return nil, err
}
return &creditcontracts.CreditConsumptionDashboardView{
Period: period,
CreditConsumed: aggregate.CreditConsumed,
TokenConsumed: aggregate.TokenConsumed,
}, nil
}
// normalizeCreditConsumptionPeriod 只负责把前端周期值收敛到固定枚举。
//
// 1. 空值默认回落到 24h保证首页初次进入时可直接展示。
// 2. 非法值直接返回业务坏参,避免网关和前端各自维护一份不一致的枚举。
// 3. 这里不做时间计算,方便后续单独复用和测试。
func normalizeCreditConsumptionPeriod(raw string) (string, error) {
switch strings.ToLower(strings.TrimSpace(raw)) {
case "", creditcontracts.CreditConsumptionPeriod24h:
return creditcontracts.CreditConsumptionPeriod24h, nil
case creditcontracts.CreditConsumptionPeriod7d:
return creditcontracts.CreditConsumptionPeriod7d, nil
case creditcontracts.CreditConsumptionPeriod30d:
return creditcontracts.CreditConsumptionPeriod30d, nil
case creditcontracts.CreditConsumptionPeriodAll:
return creditcontracts.CreditConsumptionPeriodAll, nil
default:
return "", tokenStoreBadRequest("period 仅支持 24h、7d、30d 或 all")
}
}
// resolveCreditConsumptionWindowStart 负责把固定周期映射为统计起点。
//
// 1. only "all" 返回 nil表示不加 created_at 过滤。
// 2. 其它周期统一按当前时间回退固定时长,保证前后端口径一致。
// 3. 这里不处理时区格式化,因为最终查询直接使用 time.Time 传给 DAO。
func resolveCreditConsumptionWindowStart(period string, now time.Time) *time.Time {
var startAt time.Time
switch period {
case creditcontracts.CreditConsumptionPeriod24h:
startAt = now.Add(-24 * time.Hour)
case creditcontracts.CreditConsumptionPeriod7d:
startAt = now.Add(-7 * 24 * time.Hour)
case creditcontracts.CreditConsumptionPeriod30d:
startAt = now.Add(-30 * 24 * time.Hour)
default:
return nil
}
return &startAt
}