feat: SSR 友链页与最小 Admin 审核
公开 /links 列表与申请/取消,导航页脚可配入口;后台品牌增删与通过/拒绝。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
209
routers/web/admin_friend_links.go
Normal file
209
routers/web/admin_friend_links.go
Normal file
@@ -0,0 +1,209 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.iioio.com/freefire/jiang13-forum/models"
|
||||
"git.iioio.com/freefire/jiang13-forum/modules/webctx"
|
||||
"git.iioio.com/freefire/jiang13-forum/services"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type adminFriendLinkBrandRow struct {
|
||||
Name string
|
||||
URL string
|
||||
Logo string
|
||||
}
|
||||
|
||||
type adminFriendLinkApplyRow struct {
|
||||
ID uint
|
||||
UserID uint
|
||||
Username string
|
||||
Name string
|
||||
URL string
|
||||
Logo string
|
||||
Status string
|
||||
StatusLabel string
|
||||
OnHome bool
|
||||
Reciprocal string
|
||||
RecipOK bool
|
||||
RecipNote string
|
||||
CreatedAt string
|
||||
CanReview bool
|
||||
}
|
||||
|
||||
type adminFriendLinksData struct {
|
||||
AdminChrome
|
||||
BrandLinks []adminFriendLinkBrandRow
|
||||
Applies []adminFriendLinkApplyRow
|
||||
PendingCount int64
|
||||
NavShow bool
|
||||
FooterShow bool
|
||||
ReciprocalCheck bool
|
||||
BrandName string
|
||||
BrandURL string
|
||||
BrandLogo string
|
||||
}
|
||||
|
||||
// AdminFriendLinksGet 友链管理
|
||||
func (d Deps) AdminFriendLinksGet(c *gin.Context) {
|
||||
ctx := d.ctx(c)
|
||||
d.renderAdminFriendLinks(ctx, "")
|
||||
}
|
||||
|
||||
func (d Deps) renderAdminFriendLinks(ctx *webctx.Context, errMsg string) {
|
||||
chrome := d.adminChrome(ctx, "友链", "friend-links")
|
||||
chrome.Error = errMsg
|
||||
data := adminFriendLinksData{
|
||||
AdminChrome: chrome,
|
||||
NavShow: d.Settings.NavShowFriendLinks(),
|
||||
FooterShow: d.Settings.FooterShowFriendLinks(),
|
||||
ReciprocalCheck: d.Settings.FriendLinkReciprocalCheckEnabled(),
|
||||
}
|
||||
brand := d.Settings.SiteBranding()
|
||||
for _, l := range brand.FriendLinks {
|
||||
data.BrandLinks = append(data.BrandLinks, adminFriendLinkBrandRow{Name: l.Name, URL: l.URL, Logo: l.Logo})
|
||||
}
|
||||
if d.FriendLink != nil {
|
||||
data.PendingCount, _ = d.FriendLink.PendingCount()
|
||||
rows, _, _ := d.FriendLink.ListAdmin(services.FriendLinkApplyListQuery{Page: 1, Size: 50, Status: "all"})
|
||||
data.Applies = make([]adminFriendLinkApplyRow, 0, len(rows))
|
||||
for _, a := range rows {
|
||||
uname := ""
|
||||
if a.User.ID > 0 {
|
||||
uname = a.User.Username
|
||||
}
|
||||
data.Applies = append(data.Applies, adminFriendLinkApplyRow{
|
||||
ID: a.ID,
|
||||
UserID: a.UserID,
|
||||
Username: uname,
|
||||
Name: a.Name,
|
||||
URL: a.URL,
|
||||
Logo: a.Logo,
|
||||
Status: a.Status,
|
||||
StatusLabel: friendLinkApplyStatusLabel(a.Status),
|
||||
OnHome: a.LinkOnHomepage,
|
||||
Reciprocal: a.ReciprocalPageURL,
|
||||
RecipOK: a.ReciprocalVerified,
|
||||
RecipNote: a.ReciprocalCheckNote,
|
||||
CreatedAt: a.CreatedAt.Format("2006-01-02 15:04"),
|
||||
CanReview: a.Status == models.FriendLinkApplyStatusPending,
|
||||
})
|
||||
}
|
||||
}
|
||||
ctx.HTML(http.StatusOK, "admin/friend_links", data)
|
||||
}
|
||||
|
||||
// AdminFriendLinksSettingsPost nav/footer/回链开关
|
||||
func (d Deps) AdminFriendLinksSettingsPost(c *gin.Context) {
|
||||
ctx := d.ctx(c)
|
||||
if !ctx.CheckCSRF() {
|
||||
d.renderAdminFriendLinks(ctx, "无效请求,请重试")
|
||||
return
|
||||
}
|
||||
_ = d.Settings.SetNavShowFriendLinks(c.PostForm("nav_show") == "1" || c.PostForm("nav_show") == "on")
|
||||
_ = d.Settings.SetFooterShowFriendLinks(c.PostForm("footer_show") == "1" || c.PostForm("footer_show") == "on")
|
||||
_ = d.Settings.SetFriendLinkReciprocalCheckEnabled(c.PostForm("reciprocal_check") == "1" || c.PostForm("reciprocal_check") == "on")
|
||||
ctx.SetFlash("友链入口设置已保存")
|
||||
ctx.Redirect("/admin/friend-links")
|
||||
}
|
||||
|
||||
// AdminFriendLinksBrandAddPost 添加品牌友链
|
||||
func (d Deps) AdminFriendLinksBrandAddPost(c *gin.Context) {
|
||||
ctx := d.ctx(c)
|
||||
name := strings.TrimSpace(c.PostForm("name"))
|
||||
url := strings.TrimSpace(c.PostForm("url"))
|
||||
logo := strings.TrimSpace(c.PostForm("logo"))
|
||||
if !ctx.CheckCSRF() {
|
||||
d.renderAdminFriendLinks(ctx, "无效请求,请重试")
|
||||
return
|
||||
}
|
||||
brand := d.Settings.SiteBranding()
|
||||
next := append([]services.FriendLink{}, brand.FriendLinks...)
|
||||
next = append(next, services.FriendLink{Name: name, URL: url, Logo: logo})
|
||||
if err := d.Settings.UpdateSiteBranding(services.SiteBranding{
|
||||
Name: brand.Name, Slogan: brand.Slogan, Description: brand.Description,
|
||||
Keywords: brand.Keywords, LogoMark: brand.LogoMark, Logo: brand.Logo,
|
||||
Favicon: brand.Favicon, OGImage: brand.OGImage,
|
||||
ICPBeian: brand.ICPBeian, ICPBeianURL: brand.ICPBeianURL,
|
||||
FriendLinks: next,
|
||||
}); err != nil {
|
||||
d.renderAdminFriendLinks(ctx, err.Error())
|
||||
return
|
||||
}
|
||||
ctx.SetFlash("已添加品牌友链")
|
||||
ctx.Redirect("/admin/friend-links")
|
||||
}
|
||||
|
||||
// AdminFriendLinksBrandDeletePost 删除品牌友链(按 URL)
|
||||
func (d Deps) AdminFriendLinksBrandDeletePost(c *gin.Context) {
|
||||
ctx := d.ctx(c)
|
||||
if !ctx.CheckCSRF() {
|
||||
d.renderAdminFriendLinks(ctx, "无效请求,请重试")
|
||||
return
|
||||
}
|
||||
target := strings.TrimSpace(c.PostForm("url"))
|
||||
brand := d.Settings.SiteBranding()
|
||||
next := make([]services.FriendLink, 0, len(brand.FriendLinks))
|
||||
for _, l := range brand.FriendLinks {
|
||||
if l.URL == target {
|
||||
continue
|
||||
}
|
||||
next = append(next, l)
|
||||
}
|
||||
if err := d.Settings.UpdateSiteBranding(services.SiteBranding{
|
||||
Name: brand.Name, Slogan: brand.Slogan, Description: brand.Description,
|
||||
Keywords: brand.Keywords, LogoMark: brand.LogoMark, Logo: brand.Logo,
|
||||
Favicon: brand.Favicon, OGImage: brand.OGImage,
|
||||
ICPBeian: brand.ICPBeian, ICPBeianURL: brand.ICPBeianURL,
|
||||
FriendLinks: next,
|
||||
}); err != nil {
|
||||
d.renderAdminFriendLinks(ctx, err.Error())
|
||||
return
|
||||
}
|
||||
ctx.SetFlash("已删除品牌友链")
|
||||
ctx.Redirect("/admin/friend-links")
|
||||
}
|
||||
|
||||
// AdminFriendLinkApprovePost 通过申请
|
||||
func (d Deps) AdminFriendLinkApprovePost(c *gin.Context) {
|
||||
ctx := d.ctx(c)
|
||||
if !ctx.CheckCSRF() {
|
||||
d.renderAdminFriendLinks(ctx, "无效请求,请重试")
|
||||
return
|
||||
}
|
||||
if d.FriendLink == nil {
|
||||
d.renderAdminFriendLinks(ctx, "友链服务未就绪")
|
||||
return
|
||||
}
|
||||
id64, _ := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if _, err := d.FriendLink.Approve(uint(id64)); err != nil {
|
||||
d.renderAdminFriendLinks(ctx, err.Error())
|
||||
return
|
||||
}
|
||||
ctx.SetFlash("已通过友链申请")
|
||||
ctx.Redirect("/admin/friend-links")
|
||||
}
|
||||
|
||||
// AdminFriendLinkRejectPost 拒绝申请
|
||||
func (d Deps) AdminFriendLinkRejectPost(c *gin.Context) {
|
||||
ctx := d.ctx(c)
|
||||
if !ctx.CheckCSRF() {
|
||||
d.renderAdminFriendLinks(ctx, "无效请求,请重试")
|
||||
return
|
||||
}
|
||||
if d.FriendLink == nil {
|
||||
d.renderAdminFriendLinks(ctx, "友链服务未就绪")
|
||||
return
|
||||
}
|
||||
id64, _ := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
note := strings.TrimSpace(c.PostForm("note"))
|
||||
if _, err := d.FriendLink.Reject(uint(id64), note); err != nil {
|
||||
d.renderAdminFriendLinks(ctx, err.Error())
|
||||
return
|
||||
}
|
||||
ctx.SetFlash("已拒绝友链申请")
|
||||
ctx.Redirect("/admin/friend-links")
|
||||
}
|
||||
Reference in New Issue
Block a user