update
This commit is contained in:
@ -89,7 +89,9 @@ func (h *ArticleHandler) Detail(c *gin.Context) {
|
||||
response.Error(c, http.StatusBadRequest, "缺少文章 id")
|
||||
return
|
||||
}
|
||||
_, numeric, err := hashid.DecodeTyped(raw)
|
||||
// 类型由路由提供(/runway-looks 即 runway)。类型已揉进密码:非 runway 编码的串
|
||||
// 在此解出的是错误主键,查库自然 404,从而强制前端按类型化路由分流(无需靠前缀嗅探)。
|
||||
numeric, err := hashid.DecodeWithType(raw, hashid.TypeRunway)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusNotFound, "文章不存在")
|
||||
return
|
||||
@ -97,8 +99,17 @@ func (h *ArticleHandler) Detail(c *gin.Context) {
|
||||
|
||||
detail, err := h.articles.Detail(c.Request.Context(), strconv.FormatUint(uint64(numeric), 10), parseLocale(c))
|
||||
if err != nil {
|
||||
fail(c, err)
|
||||
return
|
||||
// 向后兼容:迁移前收藏/历史/旧外链可能仍带 r= 前缀(旧 EncodeTyped)。
|
||||
// 主线按类型化密码解码不到实体时,按旧编码再解一次回退(仅当旧类型确为 runway)。
|
||||
if ltyp, lnum, lerr := hashid.DecodeTyped(raw); lerr == nil && ltyp == hashid.TypeRunway {
|
||||
if d2, e2 := h.articles.Detail(c.Request.Context(), strconv.FormatUint(uint64(lnum), 10), parseLocale(c)); e2 == nil {
|
||||
detail, err = d2, nil
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
fail(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 未登录:主图只返回预览上限(PreviewLimit)张并打 preview=true,前端据此展示
|
||||
@ -112,9 +123,9 @@ func (h *ArticleHandler) Detail(c *gin.Context) {
|
||||
preview = true
|
||||
}
|
||||
|
||||
// 已登录:把当前用户对该图集(gallery 级)与每张图片(image 级,含细节图)的收藏态
|
||||
// 随详情返回,前端无需再单独调 /me/favorites/checks。gallery uid(r=)与图片 id(i=)
|
||||
// 前缀不同,混传 FilterExisting 不影响查询;匿名请求不查(保持公开接口无用户态、可缓存)。
|
||||
// 已登录:把当前用户对该图集(gallery 级 TypeRunway)与每张图片(image 级 TypeRunwayImage,含细节图)的收藏态
|
||||
// 随详情返回,前端无需再单独调 /me/favorites/checks。gallery uid 与图片 id 因类型进密码、串值不同,
|
||||
// 混传 FilterExisting 不影响查询;匿名请求不查(保持公开接口无用户态、可缓存)。
|
||||
if uid, ok := middleware.UserIDFrom(c); ok {
|
||||
ids := make([]string, 0, len(detail.Images)*2+1)
|
||||
ids = append(ids, detail.UID)
|
||||
|
||||
@ -258,10 +258,10 @@ func (h *BackstageHandler) Runways(c *gin.Context) {
|
||||
}
|
||||
|
||||
// RunwayDetail 走秀详情:展示完整图集,复用 ArticleService.Detail。
|
||||
// 路由 :id 是带 "r" 前缀的 hashid,需先解码成数字主键再查库(与公开接口 article_handler 保持一致)。
|
||||
// 路由 :id 是 runway 类型化编码(无前缀,类型进密码),按 TypeRunway 解码(与公开接口 article_handler 一致)。
|
||||
func (h *BackstageHandler) RunwayDetail(c *gin.Context) {
|
||||
raw := c.Param("id")
|
||||
_, numeric, err := hashid.DecodeTyped(raw)
|
||||
numeric, err := hashid.DecodeWithType(raw, hashid.TypeRunway)
|
||||
if err != nil {
|
||||
renderHTML(c, http.StatusNotFound, tplError, gin.H{"Error": "走秀不存在或已删除: " + raw})
|
||||
return
|
||||
@ -311,10 +311,10 @@ func (h *BackstageHandler) StreetSnaps(c *gin.Context) {
|
||||
}
|
||||
|
||||
// StreetSnapDetail 街拍详情:展示完整图集,复用 StreetSnapService.Detail。
|
||||
// 路由 :id 是带 "s" 前缀的 hashid,需先解码成数字主键再查库(与公开接口 street_snap_handler 保持一致)。
|
||||
// 路由 :id 是 snap 类型化编码(无前缀,类型进密码),按 TypeSnap 解码(与公开接口 street_snap_handler 一致)。
|
||||
func (h *BackstageHandler) StreetSnapDetail(c *gin.Context) {
|
||||
raw := c.Param("id")
|
||||
_, numeric, err := hashid.DecodeTyped(raw)
|
||||
numeric, err := hashid.DecodeWithType(raw, hashid.TypeSnap)
|
||||
if err != nil {
|
||||
renderHTML(c, http.StatusNotFound, tplError, gin.H{"Error": "街拍不存在或已删除: " + raw})
|
||||
return
|
||||
@ -590,7 +590,7 @@ func usernameString(v any) string {
|
||||
// RunwayEdit 渲染走秀编辑表单(预填现有字段 + 图片管理)。
|
||||
func (h *BackstageHandler) RunwayEdit(c *gin.Context) {
|
||||
raw := c.Param("id")
|
||||
_, numeric, err := hashid.DecodeTyped(raw)
|
||||
numeric, err := hashid.DecodeWithType(raw, hashid.TypeRunway)
|
||||
if err != nil {
|
||||
renderHTML(c, http.StatusNotFound, tplError, gin.H{"Error": "走秀不存在或已删除: " + raw})
|
||||
return
|
||||
@ -619,7 +619,7 @@ func (h *BackstageHandler) RunwayEdit(c *gin.Context) {
|
||||
// RunwayUpdate 应用走秀字段编辑。
|
||||
func (h *BackstageHandler) RunwayUpdate(c *gin.Context) {
|
||||
raw := c.Param("id")
|
||||
_, numeric, err := hashid.DecodeTyped(raw)
|
||||
numeric, err := hashid.DecodeWithType(raw, hashid.TypeRunway)
|
||||
if err != nil {
|
||||
renderHTML(c, http.StatusNotFound, tplError, gin.H{"Error": "走秀不存在或已删除: " + raw})
|
||||
return
|
||||
@ -650,7 +650,7 @@ func (h *BackstageHandler) RunwayUpdate(c *gin.Context) {
|
||||
// RunwayImageDelete 软删单张走秀图片。
|
||||
func (h *BackstageHandler) RunwayImageDelete(c *gin.Context) {
|
||||
raw := c.Param("id")
|
||||
if _, _, err := hashid.DecodeTyped(raw); err != nil {
|
||||
if _, err := hashid.DecodeWithType(raw, hashid.TypeRunway); err != nil {
|
||||
renderHTML(c, http.StatusNotFound, tplError, gin.H{"Error": "走秀不存在或已删除: " + raw})
|
||||
return
|
||||
}
|
||||
@ -669,7 +669,7 @@ func (h *BackstageHandler) RunwayImageDelete(c *gin.Context) {
|
||||
// RunwaySetCover 把某张图片设为封面。
|
||||
func (h *BackstageHandler) RunwaySetCover(c *gin.Context) {
|
||||
raw := c.Param("id")
|
||||
_, numeric, err := hashid.DecodeTyped(raw)
|
||||
numeric, err := hashid.DecodeWithType(raw, hashid.TypeRunway)
|
||||
if err != nil {
|
||||
renderHTML(c, http.StatusNotFound, tplError, gin.H{"Error": "走秀不存在或已删除: " + raw})
|
||||
return
|
||||
@ -689,7 +689,7 @@ func (h *BackstageHandler) RunwaySetCover(c *gin.Context) {
|
||||
// RunwayToggleDeleted 上下架(下架=is_deleted=1 对外不可见)。
|
||||
func (h *BackstageHandler) RunwayToggleDeleted(c *gin.Context) {
|
||||
raw := c.Param("id")
|
||||
_, numeric, err := hashid.DecodeTyped(raw)
|
||||
numeric, err := hashid.DecodeWithType(raw, hashid.TypeRunway)
|
||||
if err != nil {
|
||||
renderHTML(c, http.StatusNotFound, tplError, gin.H{"Error": "走秀不存在或已删除: " + raw})
|
||||
return
|
||||
@ -710,7 +710,7 @@ func (h *BackstageHandler) RunwayToggleDeleted(c *gin.Context) {
|
||||
// StreetSnapEdit 渲染街拍编辑表单。
|
||||
func (h *BackstageHandler) StreetSnapEdit(c *gin.Context) {
|
||||
raw := c.Param("id")
|
||||
_, numeric, err := hashid.DecodeTyped(raw)
|
||||
numeric, err := hashid.DecodeWithType(raw, hashid.TypeSnap)
|
||||
if err != nil {
|
||||
renderHTML(c, http.StatusNotFound, tplError, gin.H{"Error": "街拍不存在或已删除: " + raw})
|
||||
return
|
||||
@ -731,7 +731,7 @@ func (h *BackstageHandler) StreetSnapEdit(c *gin.Context) {
|
||||
// StreetSnapUpdate 应用街拍字段编辑。
|
||||
func (h *BackstageHandler) StreetSnapUpdate(c *gin.Context) {
|
||||
raw := c.Param("id")
|
||||
_, numeric, err := hashid.DecodeTyped(raw)
|
||||
numeric, err := hashid.DecodeWithType(raw, hashid.TypeSnap)
|
||||
if err != nil {
|
||||
renderHTML(c, http.StatusNotFound, tplError, gin.H{"Error": "街拍不存在或已删除: " + raw})
|
||||
return
|
||||
@ -757,7 +757,7 @@ func (h *BackstageHandler) StreetSnapUpdate(c *gin.Context) {
|
||||
// StreetSnapImageDelete 软删单张街拍图片。
|
||||
func (h *BackstageHandler) StreetSnapImageDelete(c *gin.Context) {
|
||||
raw := c.Param("id")
|
||||
if _, _, err := hashid.DecodeTyped(raw); err != nil {
|
||||
if _, err := hashid.DecodeWithType(raw, hashid.TypeSnap); err != nil {
|
||||
renderHTML(c, http.StatusNotFound, tplError, gin.H{"Error": "街拍不存在或已删除: " + raw})
|
||||
return
|
||||
}
|
||||
@ -776,7 +776,7 @@ func (h *BackstageHandler) StreetSnapImageDelete(c *gin.Context) {
|
||||
// StreetSnapSetCover 把某张图片设为封面。
|
||||
func (h *BackstageHandler) StreetSnapSetCover(c *gin.Context) {
|
||||
raw := c.Param("id")
|
||||
_, numeric, err := hashid.DecodeTyped(raw)
|
||||
numeric, err := hashid.DecodeWithType(raw, hashid.TypeSnap)
|
||||
if err != nil {
|
||||
renderHTML(c, http.StatusNotFound, tplError, gin.H{"Error": "街拍不存在或已删除: " + raw})
|
||||
return
|
||||
@ -796,7 +796,7 @@ func (h *BackstageHandler) StreetSnapSetCover(c *gin.Context) {
|
||||
// StreetSnapToggleDeleted 上下架。
|
||||
func (h *BackstageHandler) StreetSnapToggleDeleted(c *gin.Context) {
|
||||
raw := c.Param("id")
|
||||
_, numeric, err := hashid.DecodeTyped(raw)
|
||||
numeric, err := hashid.DecodeWithType(raw, hashid.TypeSnap)
|
||||
if err != nil {
|
||||
renderHTML(c, http.StatusNotFound, tplError, gin.H{"Error": "街拍不存在或已删除: " + raw})
|
||||
return
|
||||
|
||||
@ -74,7 +74,9 @@ func (h *StreetSnapHandler) Detail(c *gin.Context) {
|
||||
response.Error(c, http.StatusBadRequest, "缺少街拍 id")
|
||||
return
|
||||
}
|
||||
_, numeric, err := hashid.DecodeTyped(raw)
|
||||
// 类型由路由提供(/street-snaps 即 snap)。类型已揉进密码:非 snap 编码的串
|
||||
// 在此解出的是错误主键,查库自然 404,从而强制前端按类型化路由分流(无需靠前缀嗅探)。
|
||||
numeric, err := hashid.DecodeWithType(raw, hashid.TypeSnap)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusNotFound, "街拍不存在")
|
||||
return
|
||||
@ -82,8 +84,17 @@ func (h *StreetSnapHandler) Detail(c *gin.Context) {
|
||||
|
||||
detail, err := h.svc.Detail(c.Request.Context(), strconv.FormatUint(uint64(numeric), 10))
|
||||
if err != nil {
|
||||
fail(c, err)
|
||||
return
|
||||
// 向后兼容:迁移前收藏/历史/旧外链可能仍带 s= 前缀(旧 EncodeTyped)。
|
||||
// 主线按类型化密码解码不到实体时,按旧编码再解一次回退(仅当旧类型确为 snap)。
|
||||
if ltyp, lnum, lerr := hashid.DecodeTyped(raw); lerr == nil && ltyp == hashid.TypeSnap {
|
||||
if d2, e2 := h.svc.Detail(c.Request.Context(), strconv.FormatUint(uint64(lnum), 10)); e2 == nil {
|
||||
detail, err = d2, nil
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
fail(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 未登录:图片集仅返回预览上限(PreviewLimit)张,并打 preview=true,
|
||||
@ -96,7 +107,7 @@ func (h *StreetSnapHandler) Detail(c *gin.Context) {
|
||||
preview = true
|
||||
}
|
||||
|
||||
// 已登录:图集(gallery 级 s=)与每张图片(image 级 j=)收藏态随详情返回,
|
||||
// 已登录:图集(gallery 级 TypeSnap)与每张图片(image 级 TypeSnapImage)收藏态随详情返回,
|
||||
// 前端无需再单独调 /me/favorites/checks。
|
||||
if uid, ok := middleware.UserIDFrom(c); ok {
|
||||
ids := make([]string, 0, len(detail.Images)+1)
|
||||
|
||||
Reference in New Issue
Block a user