feat: 导航页SEO/GEO优化 + 手机端完全适配 + App候选码 + 业务系统板块

- SEO: 添加meta description/keywords/Open Graph/结构化数据/地理信息
- GEO: 添加geo.region/geo.position/ICBM等地理标记
- 手机端完全重写响应式: 咨询表单/导航卡片/hero区/标签全部适配
- 新增App候选码板块: 后台管理+导航页动态展示(支持录屏视频/下载链接)
- 新增业务系统板块: 进销存/OA/财务/工单等,支持按年/按月/定制定价
- 后台新增App候选码管理页面(增删改查+上下架)
- 后台新增业务系统管理页面(增删改查+上下架)
- 导航页设置新增新板块标题配置
- 公开API: GET /api/v1/showcase/apps + /api/v1/showcase/systems
This commit is contained in:
2026-09-09 03:32:22 +08:00
parent 278b07aa97
commit 69c59f4fbd
9 changed files with 629 additions and 9 deletions

View File

@@ -142,6 +142,11 @@ func (h *ConfigHandler) GetNavSettings(c *gin.Context) {
"nav_sec_app_sub",
"nav_sec_music_title",
"nav_sec_music_sub",
// 新板块
"nav_sec_appshow_title",
"nav_sec_appshow_sub",
"nav_sec_bizsys_title",
"nav_sec_bizsys_sub",
}
settings := map[string]string{}

View File

@@ -0,0 +1,191 @@
package handler
import (
"strconv"
"gotest/internal/model"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// ShowcaseHandler App 候选码 & 业务系统管理
type ShowcaseHandler struct {
db *gorm.DB
}
func NewShowcaseHandler(db *gorm.DB) *ShowcaseHandler {
return &ShowcaseHandler{db: db}
}
// ========== App 候选码 ==========
func (h *ShowcaseHandler) ListAppShowcase(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 20
}
var total int64
h.db.Model(&model.AppShowcase{}).Where("status = 1").Count(&total)
var items []model.AppShowcase
h.db.Where("status = 1").Order("sort ASC, id DESC").
Offset((page - 1) * pageSize).Limit(pageSize).Find(&items)
Success(c, gin.H{
"list": items, "total": total, "page": page, "page_size": pageSize,
})
}
func (h *ShowcaseHandler) AdminListAppShowcase(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 20
}
var total int64
h.db.Model(&model.AppShowcase{}).Count(&total)
var items []model.AppShowcase
h.db.Order("sort ASC, id DESC").
Offset((page - 1) * pageSize).Limit(pageSize).Find(&items)
Success(c, gin.H{
"list": items, "total": total, "page": page, "page_size": pageSize,
})
}
func (h *ShowcaseHandler) CreateAppShowcase(c *gin.Context) {
var item model.AppShowcase
if err := c.ShouldBindJSON(&item); err != nil {
FailBadRequest(c, "参数错误")
return
}
if err := h.db.Create(&item).Error; err != nil {
FailInternal(c, "创建失败: "+err.Error())
return
}
Success(c, item)
}
func (h *ShowcaseHandler) UpdateAppShowcase(c *gin.Context) {
id := c.Param("id")
var item model.AppShowcase
if err := h.db.First(&item, id).Error; err != nil {
Fail(c, 404, "记录不存在")
return
}
if err := c.ShouldBindJSON(&item); err != nil {
FailBadRequest(c, "参数错误")
return
}
if err := h.db.Save(&item).Error; err != nil {
FailInternal(c, "更新失败: "+err.Error())
return
}
Success(c, item)
}
func (h *ShowcaseHandler) DeleteAppShowcase(c *gin.Context) {
id := c.Param("id")
if err := h.db.Delete(&model.AppShowcase{}, id).Error; err != nil {
FailInternal(c, "删除失败: "+err.Error())
return
}
SuccessMsg(c, "删除成功")
}
// ========== 业务系统 ==========
func (h *ShowcaseHandler) ListBizSystem(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 20
}
var total int64
h.db.Model(&model.BizSystem{}).Where("status = 1").Count(&total)
var items []model.BizSystem
h.db.Where("status = 1").Order("sort ASC, id DESC").
Offset((page - 1) * pageSize).Limit(pageSize).Find(&items)
Success(c, gin.H{
"list": items, "total": total, "page": page, "page_size": pageSize,
})
}
func (h *ShowcaseHandler) AdminListBizSystem(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 20
}
var total int64
h.db.Model(&model.BizSystem{}).Count(&total)
var items []model.BizSystem
h.db.Order("sort ASC, id DESC").
Offset((page - 1) * pageSize).Limit(pageSize).Find(&items)
Success(c, gin.H{
"list": items, "total": total, "page": page, "page_size": pageSize,
})
}
func (h *ShowcaseHandler) CreateBizSystem(c *gin.Context) {
var item model.BizSystem
if err := c.ShouldBindJSON(&item); err != nil {
FailBadRequest(c, "参数错误")
return
}
if err := h.db.Create(&item).Error; err != nil {
FailInternal(c, "创建失败: "+err.Error())
return
}
Success(c, item)
}
func (h *ShowcaseHandler) UpdateBizSystem(c *gin.Context) {
id := c.Param("id")
var item model.BizSystem
if err := h.db.First(&item, id).Error; err != nil {
Fail(c, 404, "记录不存在")
return
}
if err := c.ShouldBindJSON(&item); err != nil {
FailBadRequest(c, "参数错误")
return
}
if err := h.db.Save(&item).Error; err != nil {
FailInternal(c, "更新失败: "+err.Error())
return
}
Success(c, item)
}
func (h *ShowcaseHandler) DeleteBizSystem(c *gin.Context) {
id := c.Param("id")
if err := h.db.Delete(&model.BizSystem{}, id).Error; err != nil {
FailInternal(c, "删除失败: "+err.Error())
return
}
SuccessMsg(c, "删除成功")
}