Files
hunli/hunliji-api/hotelwelcome/welcome.go
2026-08-04 08:45:09 +08:00

296 lines
7.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package hotelwelcome
import (
"encoding/json"
"strconv"
"strings"
"time"
"unicode/utf8"
"hunliji-api/models"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
var (
db *gorm.DB
requireAdmin func(*gin.Context) bool
)
var allowedTemplates = map[string]bool{
"banner-bottom": true,
"banner-top": true,
"banner-center": true,
"banner-names": true,
"banner-lower-third": true,
"banner-split-names": true,
"banner-frame-bottom": true,
"banner-minimal": true,
"art-welcome-brush": true,
"art-love-life": true,
"art-gaobai": true,
"art-married": true,
"art-hand-love": true,
"art-like-you": true,
"art-give-home": true,
"art-xi-welcome": true,
"art-wujia": true,
"art-tianci": true,
"art-tianzuo": true,
"art-welcome-v": true,
"art-longest": true,
"art-just-love": true,
"custom": true,
// 旧 key 兼容
"banner-zh": true,
"banner-upper-third": true,
"banner-mid-band": true,
"banner-left-stack": true,
"banner-right-stack": true,
"banner-vertical-left": true,
"banner-vertical-right": true,
"banner-hero-name": true,
"banner-date-focus": true,
"banner-welcome-en": true,
"banner-xi-corner": true,
"banner-top-bottom": true,
"welcome-bottom": true,
"welcome-top": true,
"welcome-left": true,
"welcome-right": true,
"welcome-center": true,
}
// Register 酒店迎宾海报 CRUD均需管理员
func Register(api *gin.RouterGroup, database *gorm.DB, adminGuard func(*gin.Context) bool) {
db = database
requireAdmin = adminGuard
api.GET("/hotel-welcome/list", handleList)
api.GET("/hotel-welcome/:id", handleDetail)
api.POST("/hotel-welcome", handleCreate)
api.PUT("/hotel-welcome/:id", handleUpdate)
api.DELETE("/hotel-welcome/:id", handleDelete)
}
func emptyConfigJSON() string {
return `{"texts":[]}`
}
func normalizeConfig(raw string) string {
raw = strings.TrimSpace(raw)
if raw == "" {
return emptyConfigJSON()
}
var m map[string]interface{}
if err := json.Unmarshal([]byte(raw), &m); err != nil {
return emptyConfigJSON()
}
if _, ok := m["texts"]; !ok {
m["texts"] = []interface{}{}
}
b, err := json.Marshal(m)
if err != nil {
return emptyConfigJSON()
}
return string(b)
}
func normalizeTemplate(raw string) string {
t := strings.TrimSpace(raw)
if allowedTemplates[t] {
return t
}
return "banner-bottom"
}
func parseID(c *gin.Context) (uint64, bool) {
id, err := strconv.ParseUint(strings.TrimSpace(c.Param("id")), 10, 64)
if err != nil || id == 0 {
c.JSON(400, gin.H{"error": "无效 ID"})
return 0, false
}
return id, true
}
// listItem 列表不返回原图 URL减轻压力
type listItem struct {
ID uint `json:"id"`
Name string `json:"name"`
Template string `json:"template"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func handleList(c *gin.Context) {
if !requireAdmin(c) {
return
}
var rows []models.HotelWelcomePoster
if err := db.Select("id", "name", "template", "created_at", "updated_at").
Order("updated_at desc, id desc").
Find(&rows).Error; err != nil {
c.JSON(500, gin.H{"error": "查询失败"})
return
}
list := make([]listItem, 0, len(rows))
for _, r := range rows {
list = append(list, listItem{
ID: r.ID,
Name: r.Name,
Template: r.Template,
CreatedAt: r.CreatedAt,
UpdatedAt: r.UpdatedAt,
})
}
c.JSON(200, gin.H{"code": 200, "data": gin.H{"list": list, "count": len(list)}})
}
func handleDetail(c *gin.Context) {
if !requireAdmin(c) {
return
}
id, ok := parseID(c)
if !ok {
return
}
var item models.HotelWelcomePoster
if err := db.First(&item, id).Error; err != nil {
c.JSON(404, gin.H{"error": "记录不存在"})
return
}
item.ConfigData = normalizeConfig(item.ConfigData)
item.Template = normalizeTemplate(item.Template)
c.JSON(200, gin.H{"code": 200, "data": item})
}
func handleCreate(c *gin.Context) {
if !requireAdmin(c) {
return
}
var body struct {
Name string `json:"name"`
ImageURL string `json:"image_url"`
Template string `json:"template"`
ConfigData json.RawMessage `json:"config_data"`
}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(400, gin.H{"error": "参数错误"})
return
}
name := strings.TrimSpace(body.Name)
imageURL := strings.TrimSpace(body.ImageURL)
if name == "" {
c.JSON(400, gin.H{"error": "请填写图片名称"})
return
}
if utf8.RuneCountInString(name) > 100 {
c.JSON(400, gin.H{"error": "图片名称过长"})
return
}
if imageURL == "" {
c.JSON(400, gin.H{"error": "请上传原图"})
return
}
if utf8.RuneCountInString(imageURL) > 768 {
c.JSON(400, gin.H{"error": "图片地址过长"})
return
}
cfg := emptyConfigJSON()
if len(body.ConfigData) > 0 {
cfg = normalizeConfig(string(body.ConfigData))
}
item := models.HotelWelcomePoster{
Name: name,
ImageURL: imageURL,
Template: normalizeTemplate(body.Template),
ConfigData: cfg,
}
if err := db.Create(&item).Error; err != nil {
c.JSON(500, gin.H{"error": "创建失败"})
return
}
c.JSON(200, gin.H{"code": 200, "msg": "已创建", "data": item})
}
func handleUpdate(c *gin.Context) {
if !requireAdmin(c) {
return
}
id, ok := parseID(c)
if !ok {
return
}
var body struct {
Name *string `json:"name"`
ImageURL *string `json:"image_url"`
Template *string `json:"template"`
ConfigData json.RawMessage `json:"config_data"`
}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(400, gin.H{"error": "参数错误"})
return
}
var item models.HotelWelcomePoster
if err := db.First(&item, id).Error; err != nil {
c.JSON(404, gin.H{"error": "记录不存在"})
return
}
if body.Name != nil {
name := strings.TrimSpace(*body.Name)
if name == "" {
c.JSON(400, gin.H{"error": "请填写图片名称"})
return
}
if utf8.RuneCountInString(name) > 100 {
c.JSON(400, gin.H{"error": "图片名称过长"})
return
}
item.Name = name
}
if body.ImageURL != nil {
imageURL := strings.TrimSpace(*body.ImageURL)
if imageURL == "" {
c.JSON(400, gin.H{"error": "请上传原图"})
return
}
if utf8.RuneCountInString(imageURL) > 768 {
c.JSON(400, gin.H{"error": "图片地址过长"})
return
}
item.ImageURL = imageURL
}
if body.Template != nil {
item.Template = normalizeTemplate(*body.Template)
}
if len(body.ConfigData) > 0 {
item.ConfigData = normalizeConfig(string(body.ConfigData))
}
if err := db.Save(&item).Error; err != nil {
c.JSON(500, gin.H{"error": "保存失败"})
return
}
item.ConfigData = normalizeConfig(item.ConfigData)
c.JSON(200, gin.H{"code": 200, "msg": "已保存", "data": item})
}
func handleDelete(c *gin.Context) {
if !requireAdmin(c) {
return
}
id, ok := parseID(c)
if !ok {
return
}
res := db.Delete(&models.HotelWelcomePoster{}, id)
if res.Error != nil {
c.JSON(500, gin.H{"error": "删除失败"})
return
}
if res.RowsAffected == 0 {
c.JSON(404, gin.H{"error": "记录不存在"})
return
}
c.JSON(200, gin.H{"code": 200, "msg": "已删除"})
}