diff --git a/README.md b/README.md index 1b2c0ac..e197993 100644 --- a/README.md +++ b/README.md @@ -242,6 +242,19 @@ product_use(product_id, user_id, user_org_id, used_amount, used_unit) └─ 写入 product_usage_log ``` +### 商店展示价与卡片行为(storefront) + +- **展示价唯一入口** `get_customer_price_display(product_id, user_org_id)`:显示价 = 资源真实定价 × 客户折扣率(专属折扣 → `'*'` 兜底 → 1.0;未登录按 `'*'` 报价,访客可见)。 +- **多价目必带表头**(2026-09-08):产品有多个价格因子时(如模型按量的 非缓存输入Token/输出tokens/缓存Token 三档),`pricing_text` 每段前拼 `factor_label`(来自定价 YAML fields 的 label),禁止输出裸的「¥2.1 元/百万 | ¥8.4 元/百万」让客户猜含义。单价目(如存储 元/GB月)不加表头;产线用 包月/包年 表头。 +- **卡片按钮按 product_type 分流**: + | product_type | 卡片点击 | 右下角 | + |---|---|---| + | pipeline | 进产线 open_tab(规划中→提示) | 订阅制说明 + 立即购买/进入产线 | + | workspace_storage / account | 弹 purchase_confirm 购买框 | 立即购买(未登录→登录后购买) | + | pipeline_llm_model / llm_model | **无点击行为**(cursor=default) | **「按量付费」文字,无按钮** | + + 模型产品不出购买入口的根因:`purchase_realtime` 只支持 account/storage/pipeline 三类(订阅/买断性质),模型消费走推理入口(会话/llm_v1)按用量落账,无需也无法「购买」。 + ## 目录结构 ``` diff --git a/product_management/core.py b/product_management/core.py index 538eb85..67afb88 100644 --- a/product_management/core.py +++ b/product_management/core.py @@ -1415,10 +1415,15 @@ class ProductManager: 'discount': discount, 'original_text': ''} # 4. 拼展示文本(折扣≠1 时同时给原价,让客户看见让利/加价幅度) + # 多价目产品(如模型按量:输入/输出/缓存三档 tokens 价)必须带因子表头, + # 否则客户看到裸的「¥2.1 元/百万 | ¥8.4 元/百万」不知道各是什么价 + # (2026-09-08 用户反馈)。factor_label 来自定价 YAML fields 的 label。 parts = [] orig_parts = [] for p in prices: head = p['label'] if p['label'] and p['label'] not in ('按量', '容量') else '' + if not head and len(prices) > 1: + head = p.get('factor_label') or p.get('factor') or '' seg = ('%s ' % head if head else '') + '¥%.4g %s' % ( p['amount'], p['unit_label'] or '元') parts.append(seg.strip()) diff --git a/wwwroot/storefront/index.ui b/wwwroot/storefront/index.ui index 6dc2cb5..b0c1367 100644 --- a/wwwroot/storefront/index.ui +++ b/wwwroot/storefront/index.ui @@ -56,6 +56,9 @@ {% set pricing_text = (cust or {}).get('pricing_text', '定价暂不可用') if (cust or {}).get('success') else ((cust or {}).get('message') or '定价暂不可用') %} {% set original_text = (cust or {}).get('original_text', '') %} {% set is_pipeline = (p.get('product_type') == 'pipeline') %} +{# 模型按量产品:不支持也无需「购买」(purchase_realtime 只支持 account/storage/pipeline), + 卡片不弹购买框、不出立即购买按钮,改为「按量付费」字样(2026-09-08 用户要求) #} +{% set is_model = (p.get('product_type') in ('pipeline_llm_model', 'llm_model')) %} {% set extra = {} %} {% if is_pipeline %} {# 产线订阅状态:已订阅→「进入产线」直达;未订阅→「立即购买」弹购买确认 #} @@ -73,7 +76,7 @@ "cheight": 15, "padding": "20px", "bgcolor": "#fff", - "cursor": "pointer", + "cursor": {{json.dumps('default' if is_model else 'pointer')}}, "gap": "8px" }, {% if is_pipeline %} @@ -96,7 +99,7 @@ } {% endif %} ], -{% else %} +{% elif not is_model %} "binds": [ { "wid": "self", @@ -221,6 +224,16 @@ } ] } +{% elif is_model %} + { + "widgettype": "Text", + "options": { + "text": "按量付费", + "fontSize": "13px", + "color": "#e74c3c", + "fontWeight": "600" + } + } {% elif userid %} { "widgettype": "Button",