diff --git a/route/question/page.go b/route/question/page.go index fda8d40..728e951 100644 --- a/route/question/page.go +++ b/route/question/page.go @@ -685,16 +685,25 @@ func New(ctx context.Context, f form.NewQuestion, pageUser *db.User, recaptcha r QuestionID: question.ID, UploaderUserID: askerUserID, }); err != nil { + // 问题在上面已经落库(db.Questions.Create),图片这一步失败必须回滚。 + // 不回滚的后果不是「少一张图」:箱主会收到一条无图提问,而提问者只看到 + // 「图片过大 / 上传失败」,以为没发出去;再想重发又会被 DuplicateGuard + // 按「同 IP + 同内容 5 分钟内重复」拦住 —— 既没发成功也重发不了。 + // DeleteByID 会连带清理追问与图片关联,并回退前面那次提问配额(+1)。 + if delErr := db.Questions.DeleteByID(ctx.Request().Context(), question.ID); delErr != nil { + logrus.WithContext(ctx.Request().Context()).WithError(delErr).Errorf( + "图片上传失败后回滚提问 %d 失败,已留下一条无图提问", question.ID) + } + if errors.Is(err, ErrUploadImageSizeTooLarge) || errors.Is(err, imagecheck.ErrImageTooLarge) { ctx.SetError(errors.New(i18n.T(ctx.Lang(), "question.errImageTooLarge")), f) ctx.Success("question/list") return - } else { - logrus.WithContext(ctx.Request().Context()).WithError(err).Error("Failed to upload image") - ctx.SetError(errors.New(i18n.T(ctx.Lang(), "question.errUploadImageFailed")), f) - ctx.Success("question/list") - return } + logrus.WithContext(ctx.Request().Context()).WithError(err).Error("Failed to upload image") + ctx.SetError(errors.New(i18n.T(ctx.Lang(), "question.errUploadImageFailed")), f) + ctx.Success("question/list") + return } }