修复和平小店商品图片和库存展示
This commit is contained in:
@@ -12,9 +12,16 @@ const priceLabel = computed(() => {
|
||||
})
|
||||
const stockText = computed(() => {
|
||||
if (!selectedProduct.value) return ''
|
||||
if (isXiaodian.value && selectedProduct.value.stockLabel) return selectedProduct.value.stockLabel
|
||||
if (isXiaodian.value && selectedProduct.value.count < 0) return '库存未公开'
|
||||
return `库存 ${selectedProduct.value.count}`
|
||||
})
|
||||
|
||||
const stockIsLow = computed(() => {
|
||||
if (!selectedProduct.value) return false
|
||||
if (isXiaodian.value && selectedProduct.value.stockLabel) return false
|
||||
return selectedProduct.value.count >= 0 && selectedProduct.value.count < 500
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -24,7 +31,7 @@ const stockText = computed(() => {
|
||||
<div class="selected-product-meta">
|
||||
<template v-if="selectedProduct">
|
||||
<span class="chip chip-score">{{ selectedProduct.score }} {{ priceLabel }}</span>
|
||||
<span class="chip chip-stock" :class="{ low: selectedProduct.count >= 0 && selectedProduct.count < 500 }">
|
||||
<span class="chip chip-stock" :class="{ low: stockIsLow }">
|
||||
{{ stockText }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
@@ -8,7 +8,13 @@ const { filteredProducts, selectedProductId, selectProduct, searchQuery, xiaodia
|
||||
const { currentActivity } = useActivity()
|
||||
const isXiaodian = computed(() => currentActivity.value?.id === 'xiaodian')
|
||||
const priceLabel = (product: { payLabel?: string }) => isXiaodian.value ? (product.payLabel || '点券') : '积分'
|
||||
const stockText = (count: number) => isXiaodian.value && count < 0 ? '库存未公开' : `库存 ${count}`
|
||||
const stockText = (product: { count: number; stockLabel?: string }) => {
|
||||
if (isXiaodian.value && product.stockLabel) return product.stockLabel
|
||||
if (isXiaodian.value && product.count < 0) return '库存未公开'
|
||||
return `库存 ${product.count}`
|
||||
}
|
||||
const stockIsLow = (product: { count: number; stockLabel?: string }) =>
|
||||
(!isXiaodian.value || !product.stockLabel) && product.count >= 0 && product.count < 500
|
||||
|
||||
const parentRef = ref<HTMLElement | null>(null)
|
||||
const itemSize = 72
|
||||
@@ -80,10 +86,10 @@ watch(xiaodianTab, () => {
|
||||
>{{ filteredProducts[item.index].score }} {{ priceLabel(filteredProducts[item.index]) }}</span>
|
||||
<span
|
||||
class="chip chip-stock"
|
||||
:class="{ low: filteredProducts[item.index].count >= 0 && filteredProducts[item.index].count < 500 }"
|
||||
:title="stockText(filteredProducts[item.index].count)"
|
||||
:class="{ low: stockIsLow(filteredProducts[item.index]) }"
|
||||
:title="stockText(filteredProducts[item.index])"
|
||||
>
|
||||
{{ stockText(filteredProducts[item.index].count) }}
|
||||
{{ stockText(filteredProducts[item.index]) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,6 +12,7 @@ export interface Product {
|
||||
payType?: number
|
||||
payLabel?: string
|
||||
count: number
|
||||
stockLabel?: string
|
||||
pic: string
|
||||
status: number
|
||||
openStatus: number
|
||||
|
||||
@@ -261,7 +261,7 @@ type xiaodianItem struct {
|
||||
Price string `json:"iPrice"`
|
||||
JB2Price string `json:"iJb2Price"`
|
||||
PayType string `json:"sPayType"`
|
||||
GoodsLeft string `json:"iGoodsLeft"`
|
||||
GoodsLeft xiaodianFlexibleString `json:"iGoodsLeft"`
|
||||
GoodsPic string `json:"sGoodsPic"`
|
||||
ShowBegin string `json:"dtShowBeginTime"`
|
||||
ShowEnd string `json:"dtShowEndTime"`
|
||||
@@ -548,6 +548,7 @@ func (c *DouyuClient) xiaodianProducts(cookie string, options types.XiaodianProd
|
||||
}
|
||||
seen[item.GoodsID] = struct{}{}
|
||||
payType, payLabel, price := xiaodianPayment(item)
|
||||
stock, stockLabel := xiaodianStock(item.GoodsLeft)
|
||||
products = append(products, types.Product{
|
||||
CommodityID: item.GoodsID,
|
||||
CommodityName: item.GoodsName,
|
||||
@@ -556,13 +557,46 @@ func (c *DouyuClient) xiaodianProducts(cookie string, options types.XiaodianProd
|
||||
Score: price,
|
||||
PayType: payType,
|
||||
PayLabel: payLabel,
|
||||
Count: parseXiaodianInt(item.GoodsLeft),
|
||||
Pic: item.GoodsPic,
|
||||
Count: stock,
|
||||
StockLabel: stockLabel,
|
||||
Pic: xiaodianImageURL(item.GoodsPic),
|
||||
})
|
||||
}
|
||||
return products, nil
|
||||
}
|
||||
|
||||
// xiaodianStock 保留道具接口的展示语义。iGoodsLeft 除数字外还会返回“999+”和“-1”,
|
||||
// 前者不是售罄,后者表示库存未公开,二者都不能按 strconv.Atoi 失败后归零处理。
|
||||
func xiaodianStock(value xiaodianFlexibleString) (int, string) {
|
||||
raw := strings.TrimSpace(string(value))
|
||||
switch raw {
|
||||
case "", "-1":
|
||||
return -1, "库存未公开"
|
||||
}
|
||||
if strings.HasSuffix(raw, "+") {
|
||||
minimum, err := strconv.Atoi(strings.TrimSuffix(raw, "+"))
|
||||
if err == nil && minimum >= 0 {
|
||||
return minimum, "库存 " + raw
|
||||
}
|
||||
return -1, "库存未公开"
|
||||
}
|
||||
stock, err := strconv.Atoi(raw)
|
||||
if err != nil || stock < 0 {
|
||||
return -1, "库存未公开"
|
||||
}
|
||||
return stock, ""
|
||||
}
|
||||
|
||||
// xiaodianImageURL 与官方页面一致,使用 OSS 图片的 HTTPS 地址,避免桌面 WebView 拦截 HTTP 资源。
|
||||
func xiaodianImageURL(raw string) string {
|
||||
endpoint, err := url.Parse(strings.TrimSpace(raw))
|
||||
if err != nil || endpoint.Scheme != "http" || endpoint.Hostname() != "ossweb-img.qq.com" {
|
||||
return raw
|
||||
}
|
||||
endpoint.Scheme = "https"
|
||||
return endpoint.String()
|
||||
}
|
||||
|
||||
func xiaodianPayment(item xiaodianItem) (int, string, int) {
|
||||
payType := 1
|
||||
label := "点券"
|
||||
|
||||
@@ -183,7 +183,7 @@ func TestProductsAutomaticallyResolvesXiaodianRoleAndPaginates(t *testing.T) {
|
||||
} else {
|
||||
switch offset {
|
||||
case "0":
|
||||
items = []map[string]string{{"iGoodsId": "g1", "iActionId": "act-g1", "sGoodsName": "商品一", "iCategoryId": "1", "iPrice": "10", "sPayType": "qpqb", "iGoodsLeft": "-1"}, {"iGoodsId": "g2", "sGoodsName": "特惠商品", "iCategoryId": "45", "iPrice": "0", "iJb2Price": "20", "sPayType": "jb2", "iGoodsLeft": "3"}}
|
||||
items = []map[string]string{{"iGoodsId": "g1", "iActionId": "act-g1", "sGoodsName": "商品一", "iCategoryId": "1", "iPrice": "10", "sPayType": "qpqb", "iGoodsLeft": "999+", "sGoodsPic": "http://ossweb-img.qq.com/images/test.png"}, {"iGoodsId": "g2", "sGoodsName": "特惠商品", "iCategoryId": "45", "iPrice": "0", "iJb2Price": "20", "sPayType": "jb2", "iGoodsLeft": "3"}}
|
||||
case "2":
|
||||
items = []map[string]string{{"iGoodsId": "g2", "sGoodsName": "重复商品", "iCategoryId": "45", "iPrice": "0", "iJb2Price": "20", "sPayType": "jb2", "iGoodsLeft": "3"}, {"iGoodsId": "g4", "sGoodsName": "商品四", "iCategoryId": "1", "iPrice": "40", "sPayType": "qpqb", "iGoodsLeft": "0"}}
|
||||
}
|
||||
@@ -228,6 +228,9 @@ func TestProductsAutomaticallyResolvesXiaodianRoleAndPaginates(t *testing.T) {
|
||||
if products[0].ActionID != "act-g1" {
|
||||
t.Fatalf("商品动作 ID = %q", products[0].ActionID)
|
||||
}
|
||||
if products[0].Count != 999 || products[0].StockLabel != "库存 999+" || products[0].Pic != "https://ossweb-img.qq.com/images/test.png" {
|
||||
t.Fatalf("商品库存或图片 = %#v", products[0])
|
||||
}
|
||||
if products[0].PayType != 1 || products[0].PayLabel != "点券" || products[1].PayType != 5 || products[1].PayLabel != "扭蛋碎片" || products[1].Score != 20 {
|
||||
t.Fatalf("支付字段 = %#v", products)
|
||||
}
|
||||
|
||||
@@ -97,12 +97,15 @@ type Product struct {
|
||||
CommodityID string `json:"commodityId"`
|
||||
CommodityName string `json:"commodityName"`
|
||||
// ActionID 是和平小店商品所属的动作 ID;不同商品可能不属于同一个动作。
|
||||
ActionID string `json:"actionId,omitempty"`
|
||||
Category string `json:"category"`
|
||||
Score int `json:"score"`
|
||||
PayType int `json:"payType,omitempty"`
|
||||
PayLabel string `json:"payLabel,omitempty"`
|
||||
Count int `json:"count"`
|
||||
ActionID string `json:"actionId,omitempty"`
|
||||
Category string `json:"category"`
|
||||
Score int `json:"score"`
|
||||
PayType int `json:"payType,omitempty"`
|
||||
PayLabel string `json:"payLabel,omitempty"`
|
||||
Count int `json:"count"`
|
||||
// StockLabel 保留和平小店的非数字库存显示,例如“库存 999+”或“库存未公开”。
|
||||
// Count 仅用于可精确表示的库存数值和兼容既有调用方。
|
||||
StockLabel string `json:"stockLabel,omitempty"`
|
||||
Pic string `json:"pic"`
|
||||
Status int `json:"status"`
|
||||
OpenStatus int `json:"openStatus"`
|
||||
|
||||
Reference in New Issue
Block a user