fix: 兼容档口货号括号与前导零 (#273)
This commit is contained in:
@@ -5,11 +5,11 @@ import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"cmautobuy/admin/model"
|
||||
"cmautobuy/admin/repository"
|
||||
@@ -419,19 +419,103 @@ func innerCodeStallMatches(stall string, item syb.DetailItem) bool {
|
||||
if strings.Contains(blob, stall) {
|
||||
return true
|
||||
}
|
||||
name, article, hasArticle := strings.Cut(stall, "#")
|
||||
name, article, hasArticle := splitInnerCodeStall(stall)
|
||||
if !hasArticle {
|
||||
return false
|
||||
}
|
||||
name, article = strings.TrimSpace(name), strings.TrimSpace(article)
|
||||
if article != "" {
|
||||
if strings.Contains(blob, "#"+article) || strings.HasPrefix(item.ProductSpec, article+" ") || strings.HasPrefix(item.ProductSpec, article+",") {
|
||||
if article == "" {
|
||||
return name != "" && (strings.Contains(sku, name) || strings.Contains(variation, name))
|
||||
}
|
||||
|
||||
// 纯数字货号容易在不同档口重复。只有候选也包含同一档口名称时,
|
||||
// 才允许把 067 与 67 视为同一个货号;不能只凭短数字自动选商品。
|
||||
if isInnerCodeNumericArticle(article) {
|
||||
nameMatches := name != "" && (strings.Contains(sku, name) || strings.Contains(variation, name))
|
||||
if !nameMatches {
|
||||
return false
|
||||
}
|
||||
return innerCodeTextHasNumericArticle(sku, article) ||
|
||||
innerCodeTextHasNumericArticle(variation, article) ||
|
||||
innerCodeTextHasNumericArticle(item.ProductSpec, article)
|
||||
}
|
||||
|
||||
return innerCodeTextHasExactArticle(sku, article) ||
|
||||
innerCodeTextHasExactArticle(variation, article) ||
|
||||
innerCodeTextHasExactArticle(item.ProductSpec, article)
|
||||
}
|
||||
|
||||
// splitInnerCodeStall 从“档口名称#货号”取最后一个 #,避免档口名称本身含 # 时截错。
|
||||
func splitInnerCodeStall(stall string) (name, article string, ok bool) {
|
||||
stall = strings.TrimSpace(stall)
|
||||
separator := strings.LastIndex(stall, "#")
|
||||
if separator < 0 {
|
||||
return stall, "", false
|
||||
}
|
||||
return strings.TrimSpace(stall[:separator]), strings.TrimSpace(stall[separator+1:]), true
|
||||
}
|
||||
|
||||
func isInnerCodeNumericArticle(article string) bool {
|
||||
if article == "" {
|
||||
return false
|
||||
}
|
||||
for _, char := range article {
|
||||
if !unicode.IsDigit(char) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func innerCodeTextHasNumericArticle(text, article string) bool {
|
||||
target := normalizeInnerCodeNumericArticle(article)
|
||||
for _, token := range innerCodeArticleTokens(text) {
|
||||
if isInnerCodeNumericArticle(token) && normalizeInnerCodeNumericArticle(token) == target {
|
||||
return true
|
||||
}
|
||||
pattern := regexp.MustCompile(`(?:^|[#\-_/\s])` + regexp.QuoteMeta(article) + `(?:$|[#\-_/,\s])`)
|
||||
return pattern.MatchString(sku) || pattern.MatchString(variation)
|
||||
}
|
||||
return name != "" && (strings.Contains(sku, name) || strings.Contains(variation, name))
|
||||
return false
|
||||
}
|
||||
|
||||
func normalizeInnerCodeNumericArticle(article string) string {
|
||||
normalized := strings.TrimLeft(article, "0")
|
||||
if normalized == "" {
|
||||
return "0"
|
||||
}
|
||||
return normalized
|
||||
}
|
||||
|
||||
func innerCodeTextHasExactArticle(text, article string) bool {
|
||||
for _, token := range innerCodeArticleTokens(text) {
|
||||
if token == article {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// innerCodeArticleTokens 只把连续字母或数字视为货号候选。
|
||||
// `【】`、`#`、横线、空格等标点自然成为边界,因此能识别 `067【档口】`,
|
||||
// 又不会把 `PDD256437` 中间的数字误认为独立货号。
|
||||
func innerCodeArticleTokens(text string) []string {
|
||||
tokens := make([]string, 0)
|
||||
start := -1
|
||||
runes := []rune(text)
|
||||
for index, char := range runes {
|
||||
if unicode.IsLetter(char) || unicode.IsDigit(char) {
|
||||
if start < 0 {
|
||||
start = index
|
||||
}
|
||||
continue
|
||||
}
|
||||
if start >= 0 {
|
||||
tokens = append(tokens, string(runes[start:index]))
|
||||
start = -1
|
||||
}
|
||||
}
|
||||
if start >= 0 {
|
||||
tokens = append(tokens, string(runes[start:]))
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
|
||||
func innerCodeRawText(value any) string {
|
||||
|
||||
Reference in New Issue
Block a user