Files
jiu/backend/internal/handler/shop.go
T
wangjia a05f9bd4ec
Deploy / deploy (push) Failing after 8s
feat(shop): 门店 logo 上传 + 侧边栏品牌替换
- shops 表新增 logo_url 字段,AutoMigrate 自动建列
- 后端新增 POST /api/v1/shop/logo 接口(管理员),图片裁剪为 256×256 JPEG 存储
- UpdateInfo 支持传入 logo_url
- 侧边栏「岩美」替换为门店真实名称 + 自定义 logo
- 无 logo 时显示店名首字文字头像(深蓝底白字)
- 设置页「酒行信息」展示 logo 预览,编辑弹窗新增「更换 Logo」上传按钮
- 修复库存导入计数逻辑:total/imported/updated/errors 四项分别统计
- 库存导入去重改为双路索引(编号 + 名称|系列|规格),避免 key 不一致误判新增
- settings 页导入结果统一显示「重复 X 条」,兼容 skipped 和 updated 两个字段

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 20:03:43 +08:00

119 lines
3.1 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 handler
import (
"fmt"
"image"
_ "image/jpeg"
_ "image/png"
"net/http"
"os"
"path/filepath"
"github.com/disintegration/imaging"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"github.com/wangjia/jiu/backend/config"
"github.com/wangjia/jiu/backend/internal/middleware"
"github.com/wangjia/jiu/backend/internal/model"
)
type ShopHandler struct {
db *gorm.DB
}
func NewShopHandler(db *gorm.DB) *ShopHandler {
return &ShopHandler{db: db}
}
// GetInfo GET /api/v1/shop/info
func (h *ShopHandler) GetInfo(c *gin.Context) {
shopID := middleware.GetShopID(c)
var shop model.Shop
if err := h.db.First(&shop, shopID).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "shop not found"})
return
}
c.JSON(http.StatusOK, shop)
}
// UpdateInfo PUT /api/v1/shop/info (admin only)
func (h *ShopHandler) UpdateInfo(c *gin.Context) {
shopID := middleware.GetShopID(c)
var req struct {
Name string `json:"name"`
Address string `json:"address"`
Phone string `json:"phone"`
ManagerName string `json:"manager_name"`
LogoURL string `json:"logo_url"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
updates := map[string]interface{}{
"name": req.Name,
"address": req.Address,
"phone": req.Phone,
"manager_name": req.ManagerName,
}
if req.LogoURL != "" {
updates["logo_url"] = req.LogoURL
}
if err := h.db.Model(&model.Shop{}).Where("id = ?", shopID).Updates(updates).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
var shop model.Shop
h.db.First(&shop, shopID)
c.JSON(http.StatusOK, shop)
}
// UploadLogo POST /api/v1/shop/logo (admin only)
func (h *ShopHandler) UploadLogo(c *gin.Context) {
shopID := middleware.GetShopID(c)
if err := c.Request.ParseMultipartForm(2 << 20); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "文件超过 2MB 限制"})
return
}
file, _, err := c.Request.FormFile("file")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请上传文件(field: file"})
return
}
defer file.Close()
img, _, err := image.Decode(file)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "仅支持 JPEG/PNG 图片"})
return
}
// 裁剪为正方形后缩放到 256×256
resized := imaging.Fill(img, 256, 256, imaging.Center, imaging.Lanczos)
subdir := filepath.Join(config.C.Storage.UploadDir, "shops", fmt.Sprintf("%d", shopID))
if err := os.MkdirAll(subdir, 0755); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "存储目录创建失败"})
return
}
fullPath := filepath.Join(subdir, "logo.jpg")
if err := imaging.Save(resized, fullPath, imaging.JPEGQuality(90)); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "图片保存失败"})
return
}
logoURL := fmt.Sprintf("/images/shops/%d/logo.jpg", shopID)
if err := h.db.Model(&model.Shop{}).Where("id = ?", shopID).Update("logo_url", logoURL).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"logo_url": logoURL})
}