fix templates v1
This commit is contained in:
@@ -73,6 +73,16 @@ func Questioner(ctx context.Context, pageUser *db.User) {
|
||||
ctx.Map(canDelete)
|
||||
ctx.Data["CanDelete"] = canDelete
|
||||
|
||||
// 箱主导航:下一条未读。只查一条(不做 count),用于决定详情页是否渲染该按钮。
|
||||
if canDelete {
|
||||
nextUnread, err := db.Questions.NextUnread(ctx.Request().Context(), pageUser.ID, question.ID)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx.Request().Context()).WithError(err).Error("Failed to get next unread question")
|
||||
} else if nextUnread != nil {
|
||||
ctx.Data["NextUnreadID"] = nextUnread.ID
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- 追问 ----------
|
||||
followUps, err := db.FollowUps.GetByQuestionID(ctx.Request().Context(), questionID)
|
||||
if err != nil {
|
||||
@@ -116,18 +126,14 @@ func Questioner(ctx context.Context, pageUser *db.User) {
|
||||
ctx.Data["BackFrom"] = backFrom
|
||||
// 从后台返回时,把进入时携带的筛选参数(sort/status/type/read/q)原样回传,
|
||||
// 使"返回"跳回带筛选条件的后台列表,避免丢失已选的筛选/搜索条件。
|
||||
if backFrom == "admin" {
|
||||
backQuery := url.Values{}
|
||||
for _, key := range []string{"sort", "status", "type", "read", "q"} {
|
||||
if v := ctx.Query(key); v != "" {
|
||||
backQuery.Set(key, v)
|
||||
}
|
||||
}
|
||||
// 「下一条未读」同样带上这份参数,否则答完一条后"返回"就掉回箱主页了。
|
||||
if backQuery := adminBackQuery(ctx); backFrom == "admin" {
|
||||
backTo := "/user/questions"
|
||||
if qs := backQuery.Encode(); qs != "" {
|
||||
backTo += "?" + qs
|
||||
if backQuery != "" {
|
||||
backTo += "?" + backQuery
|
||||
}
|
||||
ctx.Data["BackTo"] = backTo
|
||||
ctx.Data["NextQuery"] = backQuery
|
||||
}
|
||||
|
||||
ctx.Map(question)
|
||||
@@ -258,6 +264,18 @@ func PublishAnswer(ctx context.Context, pageUser *db.User, question *db.Question
|
||||
} else {
|
||||
ctx.SetSuccessFlash(i18n.T(ctx.Lang(), "question.flash.answered"))
|
||||
}
|
||||
|
||||
// 「回答并下一条」:同一表单的第二个提交按钮带 next=1。答题后本条已锁定为已读,
|
||||
// 直接打开最早的一条未读;队列已空(渲染后被打空的竞态)则退回当前页。
|
||||
if ctx.Request().FormValue("next") == "1" {
|
||||
nextUnread, err := db.Questions.NextUnread(ctx.Request().Context(), pageUser.ID, question.ID)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx.Request().Context()).WithError(err).Error("Failed to get next unread question")
|
||||
} else if nextUnread != nil {
|
||||
ctx.Redirect(questionPath(ctx, pageUser.Domain, nextUnread.ID))
|
||||
return
|
||||
}
|
||||
}
|
||||
ctx.Redirect(fmt.Sprintf("/_/%s/%d", pageUser.Domain, question.ID))
|
||||
}
|
||||
|
||||
@@ -396,3 +414,61 @@ func SetUnread(ctx context.Context, pageUser *db.User, question *db.Question, ca
|
||||
ctx.SetSuccessFlash(i18n.T(ctx.Lang(), "question.flash.markedUnread"))
|
||||
ctx.Redirect(fmt.Sprintf("/user/questions#question-%d", question.ID))
|
||||
}
|
||||
|
||||
// NextUnread 阅后即走:把当前提问标记为已读,然后打开最早的一条未读提问。
|
||||
//
|
||||
// 必须同时改状态:只跳转而不标记的话,当前这条仍是未读,下一次取「最早未读」
|
||||
// 又会把它选回来,两条未读之间会来回打转。
|
||||
func NextUnread(ctx context.Context, pageUser *db.User, question *db.Question, canDelete bool) {
|
||||
if !canDelete {
|
||||
ctx.Redirect("/_/" + pageUser.Domain)
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.Questions.SetRead(ctx.Request().Context(), question.ID); err != nil {
|
||||
logrus.WithContext(ctx.Request().Context()).WithError(err).Error("Failed to set question read")
|
||||
ctx.SetInternalError()
|
||||
ctx.Success("question/item")
|
||||
return
|
||||
}
|
||||
|
||||
nextUnread, err := db.Questions.NextUnread(ctx.Request().Context(), pageUser.ID, question.ID)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx.Request().Context()).WithError(err).Error("Failed to get next unread question")
|
||||
ctx.SetInternalError()
|
||||
ctx.Success("question/item")
|
||||
return
|
||||
}
|
||||
if nextUnread == nil {
|
||||
ctx.SetSuccessFlash(i18n.T(ctx.Lang(), "question.flash.noUnread"))
|
||||
ctx.Redirect(questionPath(ctx, pageUser.Domain, question.ID))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Redirect(questionPath(ctx, pageUser.Domain, nextUnread.ID))
|
||||
}
|
||||
|
||||
// questionPath 拼单题页地址;从后台进入时带上筛选参数,跳转后「返回」仍回原列表。
|
||||
func questionPath(ctx context.Context, domain string, questionID uint) string {
|
||||
path := fmt.Sprintf("/_/%s/%d", domain, questionID)
|
||||
if backQuery := adminBackQuery(ctx); backQuery != "" {
|
||||
path += "?" + backQuery
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// adminBackQuery 提取后台列表的筛选参数(仅 from=admin 时有效),供单题页的
|
||||
// 「返回」「下一条未读」沿用。POST 请求从表单 action 的 query 里读取。
|
||||
func adminBackQuery(ctx context.Context) string {
|
||||
if ctx.Query("from") != "admin" {
|
||||
return ""
|
||||
}
|
||||
|
||||
backQuery := url.Values{}
|
||||
for _, key := range []string{"sort", "status", "type", "read", "q"} {
|
||||
if v := ctx.Query(key); v != "" {
|
||||
backQuery.Set(key, v)
|
||||
}
|
||||
}
|
||||
return backQuery.Encode()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user