feat: 公开商品页重设计 + web 上传修复 + 二维码配置
- 公开商品页(/product/:uuid)全面重设计:全宽正方形图片轮播、 左右滑动切图、点击放大全屏查看、商品参数含描述、页脚贴底 - 修复 Flutter web 文件上传无反应(path→bytes) - 修复 web 路由空白页(usePathUrlStrategy + 单层 MaterialApp.router) - 二维码 URL 改为从 STORAGE_PUBLIC_URL 环境变量读取 - 新增 PUBLIC_URL dart-define → AppConfig.publicBaseUrl - 新增 CI/CD workflows + NAS runner compose 配置 - seed S001 补充商品描述字段 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,9 @@ var allModels = []any{
|
||||
&model.License{},
|
||||
&model.ProductCategory{},
|
||||
&model.Product{},
|
||||
&model.ProductNameOption{},
|
||||
&model.ProductSeriesOption{},
|
||||
&model.ProductSpecOption{},
|
||||
&model.Warehouse{},
|
||||
&model.Partner{},
|
||||
&model.StockInOrder{},
|
||||
@@ -50,7 +53,7 @@ var truncateOrder = []string{
|
||||
"stock_in_items", "stock_in_orders",
|
||||
"finance_records", "number_rules",
|
||||
"partners", "warehouses",
|
||||
"products", "product_categories",
|
||||
"products", "product_spec_options", "product_series_options", "product_name_options", "product_categories",
|
||||
"licenses", "users", "shops",
|
||||
}
|
||||
|
||||
@@ -186,14 +189,14 @@ func main() {
|
||||
remark string
|
||||
}
|
||||
prodSeeds := []prodSeed{
|
||||
{"MT-001", "6901234567890", "飞天茅台 53度 500ml", "茅台", "500ml/瓶", "瓶", "贵州茅台", &catBaijiu.ID, 2350, 2800, 10, "酱香型白酒,53度,飞天系列"},
|
||||
{"WLY-001", "6902345678901", "五粮液 52度 500ml", "五粮液", "500ml/瓶", "瓶", "宜宾五粮液", &catBaijiu.ID, 950, 1200, 6, "浓香型白酒,52度,普五系列"},
|
||||
{"YH-001", "6903456789012", "洋河梦之蓝 M6 500ml", "洋河", "500ml/瓶", "瓶", "江苏洋河", &catBaijiu.ID, 560, 680, 6, "浓香型,绵柔苏酒代表"},
|
||||
{"LZ-001", "6904567890123", "泸州老窖 特曲 500ml", "泸州老窖", "500ml/瓶", "瓶", "泸州老窖", &catBaijiu.ID, 420, 520, 6, "浓香鼻祖,特曲系列"},
|
||||
{"JNC-001", "6905678901234", "剑南春 水晶剑 500ml", "剑南春", "500ml/瓶", "瓶", "剑南春", &catBaijiu.ID, 390, 480, 6, "浓香型,绵竹名酒"},
|
||||
{"LJ-001", "6906789012345", "郎酒 红花郎10 500ml", "郎酒", "500ml/瓶", "瓶", "古蔺郎酒", &catBaijiu.ID, 320, 420, 6, "酱香型,赤水河畔酿造"},
|
||||
{"LF-001", "3760093550058", "拉菲古堡 2018 750ml", "波尔多", "750ml/瓶", "瓶", "Château Lafite", &catImport.ID, 3800, 5200, 3, "波尔多一级名庄,2018年份"},
|
||||
{"RTM-001", "3021691010008", "人头马 VSOP 700ml", "人头马", "700ml/瓶", "瓶", "Rémy Martin", &catImport.ID, 480, 680, 3, "法国干邑,VSOP级别"},
|
||||
{"MT-001", "6901234567890", "飞天茅台 53度", "茅台", "500ml/瓶", "瓶", "贵州茅台", &catBaijiu.ID, 2350, 2800, 10, "酱香型白酒,53度,飞天系列"},
|
||||
{"WLY-001", "6902345678901", "五粮液 52度", "五粮液", "500ml/瓶", "瓶", "宜宾五粮液", &catBaijiu.ID, 950, 1200, 6, "浓香型白酒,52度,普五系列"},
|
||||
{"YH-001", "6903456789012", "洋河梦之蓝 M6", "洋河", "500ml/瓶", "瓶", "江苏洋河", &catBaijiu.ID, 560, 680, 6, "浓香型,绵柔苏酒代表"},
|
||||
{"LZ-001", "6904567890123", "泸州老窖 特曲", "泸州老窖", "500ml/瓶", "瓶", "泸州老窖", &catBaijiu.ID, 420, 520, 6, "浓香鼻祖,特曲系列"},
|
||||
{"JNC-001", "6905678901234", "剑南春 水晶剑", "剑南春", "500ml/瓶", "瓶", "剑南春", &catBaijiu.ID, 390, 480, 6, "浓香型,绵竹名酒"},
|
||||
{"LJ-001", "6906789012345", "郎酒 红花郎10", "郎酒", "500ml/瓶", "瓶", "古蔺郎酒", &catBaijiu.ID, 320, 420, 6, "酱香型,赤水河畔酿造"},
|
||||
{"LF-001", "3760093550058", "拉菲古堡 2018", "波尔多", "750ml/瓶", "瓶", "Château Lafite", &catImport.ID, 3800, 5200, 3, "波尔多一级名庄,2018年份"},
|
||||
{"RTM-001", "3021691010008", "人头马 VSOP", "人头马", "700ml/瓶", "瓶", "Rémy Martin", &catImport.ID, 480, 680, 3, "法国干邑,VSOP级别"},
|
||||
}
|
||||
var prods []model.Product
|
||||
for _, s := range prodSeeds {
|
||||
@@ -209,6 +212,52 @@ func main() {
|
||||
prods = append(prods, p)
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════
|
||||
// 商品名称/系列/规格选项
|
||||
// ═══════════════════════════════════════════════════
|
||||
type dimSeed struct{ code, name string }
|
||||
|
||||
for _, s := range []dimSeed{
|
||||
{"NA001", "飞天茅台 53度"}, {"NA002", "五粮液 52度"}, {"NA003", "洋河梦之蓝 M6"},
|
||||
{"NA004", "泸州老窖 特曲"}, {"NA005", "剑南春 水晶剑"}, {"NA006", "郎酒 红花郎10"},
|
||||
{"NA007", "拉菲古堡 2018"}, {"NA008", "人头马 VSOP"},
|
||||
} {
|
||||
var opt model.ProductNameOption
|
||||
if db.Where("shop_id = ? AND name = ?", shop.ID, s.name).First(&opt).Error != nil {
|
||||
opt = model.ProductNameOption{TenantBase: model.TenantBase{ShopID: shop.ID}, Code: s.code, Name: s.name}
|
||||
db.Create(&opt)
|
||||
fmt.Printf("✅ 名称选项:%s %s\n", s.code, s.name)
|
||||
}
|
||||
}
|
||||
|
||||
for _, s := range []dimSeed{
|
||||
{"SE001", "茅台"}, {"SE002", "五粮液"}, {"SE003", "洋河"}, {"SE004", "泸州老窖"},
|
||||
{"SE005", "剑南春"}, {"SE006", "郎酒"}, {"SE007", "波尔多"}, {"SE008", "人头马"},
|
||||
} {
|
||||
var opt model.ProductSeriesOption
|
||||
if db.Where("shop_id = ? AND name = ?", shop.ID, s.name).First(&opt).Error != nil {
|
||||
opt = model.ProductSeriesOption{TenantBase: model.TenantBase{ShopID: shop.ID}, Code: s.code, Name: s.name}
|
||||
db.Create(&opt)
|
||||
fmt.Printf("✅ 系列选项:%s %s\n", s.code, s.name)
|
||||
}
|
||||
}
|
||||
|
||||
for _, s := range []struct{ code, name string; quantity int }{
|
||||
{"GG001", "500ml/瓶", 1}, {"GG002", "750ml/瓶", 1}, {"GG003", "700ml/瓶", 1},
|
||||
} {
|
||||
var opt model.ProductSpecOption
|
||||
if db.Where("shop_id = ? AND name = ?", shop.ID, s.name).First(&opt).Error != nil {
|
||||
opt = model.ProductSpecOption{
|
||||
TenantBase: model.TenantBase{ShopID: shop.ID},
|
||||
Code: s.code,
|
||||
Name: s.name,
|
||||
Quantity: s.quantity,
|
||||
}
|
||||
db.Create(&opt)
|
||||
fmt.Printf("✅ 规格选项:%s\n", s.name)
|
||||
}
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════
|
||||
// 往来单位
|
||||
// ═══════════════════════════════════════════════════
|
||||
|
||||
Reference in New Issue
Block a user