feat: Rock 回库支持上游校验与强制释放,新增 Token 状态历史

This commit is contained in:
2026-11-09 13:38:57 +08:00
parent b90252c093
commit 38cbb37a08
26 changed files with 1376 additions and 140 deletions
+65 -7
View File
@@ -22,6 +22,14 @@ func NewRockHandler(rockSvc *service.RockService) *RockHandler {
return &RockHandler{rockSvc: rockSvc}
}
// actorPtr 把 0 值用户 ID 转成 nil,便于审计字段留空。
func actorPtr(id uint) *uint {
if id == 0 {
return nil
}
return &id
}
// GetConfig 获取 Rock 平台配置
func (h *RockHandler) GetConfig(c *gin.Context) {
cfg, err := h.rockSvc.GetConfig(c.Request.Context())
@@ -395,25 +403,75 @@ func (h *RockHandler) ResetToken(c *gin.Context) {
response.BadRequest(c, "无效的 Token ID")
return
}
if err := h.rockSvc.ResetMismatchToken(c.Request.Context(), uint(idUint)); err != nil {
if err := h.rockSvc.ResetMismatchToken(c.Request.Context(), uint(idUint), actorPtr(middleware.GetUserID(c))); err != nil {
response.BadRequest(c, err.Error())
return
}
response.OK(c, gin.H{"message": "重置成功,Token 已重新释放至可用库存"})
}
// ReleaseToken 把尚未扫码绑定的使用中链接释放回可用库存
// CheckReleaseToken 释放前校验上游状态,供人工确认弹窗展示。
func (h *RockHandler) CheckReleaseToken(c *gin.Context) {
idUint, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
response.BadRequest(c, "无效的 Token ID")
return
}
result, err := h.rockSvc.CheckReleaseToken(c.Request.Context(), uint(idUint))
if err != nil {
response.BadRequest(c, err.Error())
return
}
response.OK(c, result)
}
type releaseTokenReq struct {
Force bool `json:"force"`
ForceConfirmText string `json:"force_confirm_text"`
}
// ListTokenStatusLogs 查询 Token 的生命周期/状态流转历史。
func (h *RockHandler) ListTokenStatusLogs(c *gin.Context) {
idUint, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
response.BadRequest(c, "无效的 Token ID")
return
}
logs, err := h.rockSvc.ListTokenStatusLogs(c.Request.Context(), uint(idUint))
if err != nil {
response.BadRequest(c, err.Error())
return
}
response.OK(c, gin.H{"list": logs})
}
// ReleaseToken 把使用中的提货链接释放回可用库存;上游异常时需人工强制确认。
func (h *RockHandler) ReleaseToken(c *gin.Context) {
idUint, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
response.BadRequest(c, "无效的 Token ID")
return
}
if err := h.rockSvc.ReleaseUnboundUsingToken(c.Request.Context(), uint(idUint)); err != nil {
var req releaseTokenReq
_ = c.ShouldBindJSON(&req)
if req.Force && strings.TrimSpace(req.ForceConfirmText) != "强制释放" {
response.BadRequest(c, "请输入「强制释放」确认本次操作")
return
}
actorID := middleware.GetUserID(c)
var actor *uint
if actorID != 0 {
actor = &actorID
}
if err := h.rockSvc.ReleaseUnboundUsingToken(c.Request.Context(), uint(idUint), req.Force, actor); err != nil {
response.BadRequest(c, err.Error())
return
}
response.OK(c, gin.H{"message": "已释放回可用库存,该提货链接可以再次分配"})
message := "已释放回可用库存,该提货链接可以再次分配"
if req.Force {
message = "已强制释放回可用库存,请关注下一单使用情况"
}
response.OK(c, gin.H{"message": message})
}
// RefreshStaleTokens 一键刷新异常 Token(绑定错误 + 使用超时 + 绑定超时,同步执行,单次最多 20 条)。
@@ -446,7 +504,7 @@ func (h *RockHandler) RefreshBinding(c *gin.Context) {
response.BadRequest(c, "无效的 Token ID")
return
}
result, err := h.rockSvc.RefreshTokenBinding(c.Request.Context(), uint(idUint))
result, err := h.rockSvc.RefreshTokenBindingBy(c.Request.Context(), uint(idUint), actorPtr(middleware.GetUserID(c)))
if err != nil {
response.BadRequest(c, err.Error())
return
@@ -486,7 +544,7 @@ func (h *RockHandler) UpdateRemark(c *gin.Context) {
response.BadRequest(c, "参数解析失败")
return
}
token, err := h.rockSvc.UpdateTokenRemark(c.Request.Context(), uint(idUint), req.Remark, req.Status)
token, err := h.rockSvc.UpdateTokenRemark(c.Request.Context(), uint(idUint), req.Remark, req.Status, actorPtr(middleware.GetUserID(c)))
if err != nil {
response.BadRequest(c, err.Error())
return
@@ -510,7 +568,7 @@ func (h *RockHandler) MarkAbnormal(c *gin.Context) {
}
var req markAbnormalReq
_ = c.ShouldBindJSON(&req)
token, err := h.rockSvc.MarkTokenAbnormal(c.Request.Context(), uint(idUint), req.Remark)
token, err := h.rockSvc.MarkTokenAbnormal(c.Request.Context(), uint(idUint), req.Remark, actorPtr(middleware.GetUserID(c)))
if err != nil {
response.BadRequest(c, err.Error())
return