133 lines
5.5 KiB
Go
133 lines
5.5 KiB
Go
package database
|
||
|
||
import (
|
||
"database/sql/driver"
|
||
"encoding/json"
|
||
"fmt"
|
||
"time"
|
||
)
|
||
|
||
// StringSlice 表示以 JSON 序列化形式存入 MySQL TEXT/JSON 列的字符串切片。
|
||
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(src any) error {
|
||
var raw []byte
|
||
switch v := src.(type) {
|
||
case string:
|
||
raw = []byte(v)
|
||
case []byte:
|
||
raw = v
|
||
default:
|
||
return fmt.Errorf("StringSlice: unsupported type %T", src)
|
||
}
|
||
return json.Unmarshal(raw, s)
|
||
}
|
||
|
||
// ─── 商品 ─────────────────────────────────────────────────────────────────────
|
||
|
||
// ProductRow 为 `products` 表的 GORM 模型。
|
||
type ProductRow struct {
|
||
ID string `gorm:"primaryKey;size:36"`
|
||
Name string `gorm:"size:255;not null"`
|
||
Price float64 `gorm:"not null;default:0"`
|
||
DiscountPrice float64 `gorm:"default:0"`
|
||
Tags StringSlice `gorm:"type:json"`
|
||
CoverURL string `gorm:"size:500"`
|
||
ScreenshotURLs StringSlice `gorm:"type:json"`
|
||
VerificationURL string `gorm:"size:500;default:''"`
|
||
Description string `gorm:"type:text"`
|
||
Active bool `gorm:"default:true;index"`
|
||
RequireLogin bool `gorm:"default:false"`
|
||
MaxPerAccount int `gorm:"default:0"`
|
||
TotalSold int `gorm:"default:0"`
|
||
ViewCount int `gorm:"default:0"`
|
||
DeliveryMode string `gorm:"size:20;default:'auto'"`
|
||
// FulfillmentType: card=卡密库存 / fixed=固定内容(不限库存,内容见 FixedContent)
|
||
FulfillmentType string `gorm:"size:16;default:card;index"`
|
||
FixedContent string `gorm:"type:text"`
|
||
ShowNote bool `gorm:"default:true"`
|
||
ShowContact bool `gorm:"default:true"`
|
||
// PaymentQrURLs JSON:萌芽支付等多张收款码图片链接。
|
||
PaymentQrURLs StringSlice `gorm:"column:payment_qr_urls;type:json"`
|
||
CreatedAt time.Time `gorm:"index"`
|
||
}
|
||
|
||
func (ProductRow) TableName() string { return "products" }
|
||
|
||
// ProductCodeRow 单条卡密一行,按商品维度存储。
|
||
type ProductCodeRow struct {
|
||
ID uint `gorm:"primaryKey;autoIncrement"`
|
||
ProductID string `gorm:"size:36;not null;index"`
|
||
Code string `gorm:"type:text;not null"`
|
||
}
|
||
|
||
func (ProductCodeRow) TableName() string { return "product_codes" }
|
||
|
||
// ─── 订单 ─────────────────────────────────────────────────────────────────────
|
||
|
||
type OrderRow struct {
|
||
ID string `gorm:"primaryKey;size:36"`
|
||
ProductID string `gorm:"size:36;not null;index"`
|
||
ProductName string `gorm:"size:255;not null"`
|
||
UserAccount string `gorm:"size:255;index"`
|
||
UserName string `gorm:"size:255"`
|
||
Quantity int `gorm:"not null;default:1"`
|
||
DeliveredCodes StringSlice `gorm:"type:json"`
|
||
Status string `gorm:"size:20;not null;default:'pending';index"`
|
||
DeliveryMode string `gorm:"size:20;default:'auto'"`
|
||
Note string `gorm:"type:text"`
|
||
ContactPhone string `gorm:"size:50"`
|
||
ContactEmail string `gorm:"size:255"`
|
||
NotifyEmail string `gorm:"size:255"`
|
||
// PaymentMethod 如 mengya;历史订单或免费单可能为空。
|
||
PaymentMethod string `gorm:"size:32;default:'';index"`
|
||
// PaymentExpectedTotal 待支付时应付快照(元),用于 Webhook 金额核对。
|
||
PaymentExpectedTotal float64 `gorm:"default:0"`
|
||
// PaymentExpiresAt 待支付截止时间;非待支付订单为 NULL。
|
||
PaymentExpiresAt *time.Time `gorm:"index"`
|
||
CreatedAt time.Time
|
||
}
|
||
|
||
func (OrderRow) TableName() string { return "orders" }
|
||
|
||
// ─── 站点设置 ─────────────────────────────────────────────────────────────────
|
||
|
||
// SiteSettingRow 站点级键值配置。
|
||
type SiteSettingRow struct {
|
||
Key string `gorm:"primaryKey;size:64"`
|
||
Value string `gorm:"type:text"`
|
||
}
|
||
|
||
func (SiteSettingRow) TableName() string { return "site_settings" }
|
||
|
||
// ─── 收藏夹 ───────────────────────────────────────────────────────────────────
|
||
|
||
type WishlistRow struct {
|
||
ID uint `gorm:"primaryKey;autoIncrement"`
|
||
AccountID string `gorm:"size:255;not null;index:idx_wishlist,unique"`
|
||
ProductID string `gorm:"size:36;not null;index:idx_wishlist,unique"`
|
||
}
|
||
|
||
func (WishlistRow) TableName() string { return "wishlists" }
|
||
|
||
// ─── 聊天消息 ─────────────────────────────────────────────────────────────────
|
||
|
||
type ChatMessageRow struct {
|
||
ID string `gorm:"primaryKey;size:36"`
|
||
AccountID string `gorm:"size:255;not null;index"`
|
||
AccountName string `gorm:"size:255"`
|
||
Content string `gorm:"type:text;not null"`
|
||
SentAt time.Time `gorm:"not null"`
|
||
FromAdmin bool `gorm:"default:false"`
|
||
}
|
||
|
||
func (ChatMessageRow) TableName() string { return "chat_messages" }
|