feat(backend): 意见反馈接口(提交+图片上传+admin列表)
- model/feedback.go: Feedback(多租户 shop_id,images 以 JSON 存)+ StringSlice 类型 - handler/feedback.go: Submit(认证,shop/user 从 JWT,去规范化 username/shop_code)、 UploadImage(复用 product_image 压缩逻辑,存 /images/feedback/<shop>/)、 List(SuperAdminOnly,分页过滤)、UpdateStatus(new/handled) - router 注册 /feedback、/feedback/images、/admin/feedback;main AutoMigrate;schema.sql 加表 - feedback_test 覆盖提交/校验/权限/列表 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// StringSlice 以 JSON 数组形式存储的字符串切片(用于图片 URL 列表)
|
||||
type StringSlice []string
|
||||
|
||||
func (s StringSlice) Value() (driver.Value, error) {
|
||||
if s == nil {
|
||||
return "[]", nil
|
||||
}
|
||||
b, err := json.Marshal(s)
|
||||
return string(b), err
|
||||
}
|
||||
|
||||
func (s *StringSlice) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
*s = nil
|
||||
return nil
|
||||
}
|
||||
var b []byte
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
b = []byte(v)
|
||||
case []byte:
|
||||
b = v
|
||||
default:
|
||||
return fmt.Errorf("cannot scan %T into StringSlice", value)
|
||||
}
|
||||
if len(b) == 0 {
|
||||
*s = nil
|
||||
return nil
|
||||
}
|
||||
return json.Unmarshal(b, s)
|
||||
}
|
||||
|
||||
// Feedback 用户意见反馈(bug / 功能建议):文字 + 附图。多租户按 ShopID 隔离。
|
||||
type Feedback struct {
|
||||
ID uint64 `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
ShopID uint64 `gorm:"index;not null" json:"shop_id"`
|
||||
ShopCode string `gorm:"size:50" json:"shop_code"`
|
||||
UserID uint64 `gorm:"index" json:"user_id"`
|
||||
Username string `gorm:"size:50" json:"username"`
|
||||
Role string `gorm:"size:20" json:"role"`
|
||||
Type string `gorm:"size:20;not null;index" json:"type"` // bug / suggestion
|
||||
Content string `gorm:"type:text" json:"content"`
|
||||
Images StringSlice `gorm:"type:json" json:"images"`
|
||||
AppVersion string `gorm:"size:30" json:"app_version"`
|
||||
Platform string `gorm:"size:20" json:"platform"`
|
||||
ClientIP string `gorm:"size:60" json:"client_ip"`
|
||||
Status string `gorm:"size:20;not null;default:new;index" json:"status"` // new / handled
|
||||
}
|
||||
Reference in New Issue
Block a user