feat: 完善 SYB 蝦皮主数据与软删除 (#203 #204 #205)

This commit is contained in:
chengma
2026-08-13 10:39:21 +08:00
parent 3af9bf245a
commit ad1ccc2c60
23 changed files with 864 additions and 90 deletions
+56
View File
@@ -0,0 +1,56 @@
package spec
import "strings"
// ParsedShopeeSpec 是从顺运宝规格原文中确定性得到的蝦皮规格字段。
// 解析器只接受“颜色,尺码”这种明确的二维格式,不做语义猜测。
type ParsedShopeeSpec struct {
Color string
Size string
Advice string
}
// ParseShopeeSpec 解析顺运宝常见的“颜色,尺码【建议范围】”格式。
// 返回 false 表示格式不明确,调用方应保留原文且不得写入结构化字段。
func ParseShopeeSpec(raw string) (ParsedShopeeSpec, bool) {
normalized := strings.ReplaceAll(strings.TrimSpace(raw), ",", ",")
if strings.Count(normalized, ",") != 1 {
return ParsedShopeeSpec{}, false
}
parts := strings.SplitN(normalized, ",", 2)
color, sizePart := strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])
if color == "" || sizePart == "" {
return ParsedShopeeSpec{}, false
}
size, advice := sizePart, ""
if bracket := strings.Index(sizePart, "【"); bracket >= 0 {
if !strings.HasSuffix(sizePart, "】") || strings.Count(sizePart, "【") != 1 || strings.Count(sizePart, "】") != 1 {
return ParsedShopeeSpec{}, false
}
size = strings.TrimSpace(sizePart[:bracket])
advice = strings.TrimSpace(strings.TrimSuffix(sizePart[bracket+len("【"):], "】"))
for _, prefix := range []string{"建议", "建議", "推荐", "推薦"} {
advice = strings.TrimSpace(strings.TrimPrefix(advice, prefix))
}
if advice == "" {
return ParsedShopeeSpec{}, false
}
}
size = strings.ToUpper(strings.TrimSpace(size))
if !isRecognizedSize(size) {
return ParsedShopeeSpec{}, false
}
return ParsedShopeeSpec{Color: color, Size: size, Advice: advice}, true
}
func isRecognizedSize(size string) bool {
switch size {
case "XXXS", "XXS", "XS", "S", "M", "L", "XL", "XXL", "XXXL",
"2XL", "3XL", "4XL", "5XL", "6XL", "7XL", "8XL", "9XL",
"F", "FREE", "均码", "均碼":
return true
default:
return false
}
}
+27
View File
@@ -0,0 +1,27 @@
package spec
import "testing"
func TestParseShopeeSpec(t *testing.T) {
tests := []struct {
name, raw, color, size, advice string
ok bool
}{
{"基础格式", "黑色,M", "黑色", "M", "", true},
{"全角逗号", "白色,L【建議50-60公斤】", "白色", "L", "50-60公斤", true},
{"复合颜色描述", "黑色+白色【純棉兩件裝】 簡約親膚,L【建議52.5-60公斤】", "黑色+白色【純棉兩件裝】 簡約親膚", "L", "52.5-60公斤", true},
{"数字尺码前缀", "蓝色,2xl", "蓝色", "2XL", "", true},
{"额外维度", "黑色,M,两件", "", "", "", false},
{"未知尺码", "黑色,中码", "", "", "", false},
{"空建议", "黑色,M【】", "", "", "", false},
{"缺少颜色", ",M", "", "", "", false},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
got, ok := ParseShopeeSpec(test.raw)
if ok != test.ok || got.Color != test.color || got.Size != test.size || got.Advice != test.advice {
t.Fatalf("ParseShopeeSpec(%q)=(%+v,%v),期望 (%q,%q,%q,%v)", test.raw, got, ok, test.color, test.size, test.advice, test.ok)
}
})
}
}