diff --git a/product_management/core.py b/product_management/core.py index a501e4c..bf0f7f2 100644 --- a/product_management/core.py +++ b/product_management/core.py @@ -1321,8 +1321,8 @@ class ProductManager: 全表同因子(如 flat=按次)时省略——价格列单位(元/张)已表达口径 Returns: - {'headers': [...], 'rows': [[要素值..., 价格文本]], 'html': '…'} - html 供 .ui 直接嵌入 Html 控件;让利(discount<1)时价格单元格附划线原价。 + {'headers': [...], 'rows': [[要素值..., {'t': 价格文本, 'k': 'price'}...]]} + k='orig' 的单元格是划线原价(让利时附)。.ui 用声明式控件渲染(2026-09-18)。 """ cols = [] # [(key, header)] seen = set() @@ -1350,18 +1350,9 @@ class ProductManager: headers.append('价格') rows = [] - html = ['
'] - # 主题感知(2026-09-18 暗色治理):内联样式可用 var(),跟 bricks.css 双主题变量 - th_style = ('padding:3px 6px;border:1px solid var(--line);background:var(--bg-side);' - 'color:var(--ink-3);font-weight:600;text-align:left;' - 'white-space:nowrap;') - td_style = ('padding:3px 6px;border:1px solid var(--line);color:var(--ink-2);' - 'white-space:nowrap;') - html.append('' + ''.join( - '' % (th_style, _html_escape(str(h))) - for h in headers) + '') - + # 结构化返回(2026-09-18 用户纠正:价格表用 bricks 声明式控件渲染, + # 后端不拼 HTML——Html 控件内联样式是暗色治理死角且违背声明式铁律)。 + # 单元格 = {'t': 文本, 'k': 'price'|'orig'|''},.ui 按 k 上色/划线。 for p in prices: vals = [] for key, _h in cols: @@ -1373,23 +1364,13 @@ class ProductManager: else: v = (p.get('filter_labels') or {}).get(key[2:], '') vals.append(str(v if v is not None else '')) - price_text = '¥%.4g %s' % (p['amount'], p.get('unit_label') or '元') + cells = [{'t': v, 'k': ''} for v in vals] + cells.append({'t': '¥%.4g %s' % (p['amount'], p.get('unit_label') or '元'), + 'k': 'price'}) if discount < 1.0 - 1e-9: - price_text += '(原价 ¥%.4g)' % p['original_price'] - rows.append(vals + [price_text]) - - price_html = ('%s' - % _html_escape('¥%.4g %s' % ( - p['amount'], p.get('unit_label') or '元'))) - if discount < 1.0 - 1e-9: - price_html += (' ¥%.4g' % p['original_price']) - html.append('' + ''.join( - '' % (td_style, _html_escape(v)) - for v in vals) - + '' % (td_style, price_html)) - html.append('
%s
%s%s
') - return {'headers': headers, 'rows': rows, 'html': ''.join(html)} + cells.append({'t': '¥%.4g' % p['original_price'], 'k': 'orig'}) + rows.append(cells) + return {'headers': headers, 'rows': rows} async def get_customer_price_display(self, product_id=None, product_code=None, user_org_id=None): @@ -1410,7 +1391,7 @@ class ProductManager: {'success', 'prices': [{'label','unit_price','unit_label','amount','unit', 'filter_labels','original_price'}], 'pricing_text', 'discount', 'original_text', - 'price_table': {'headers','rows','html'} 或 None(多价目时给出)} + 'price_table': {'headers': [...], 'rows': [[{'t','k'}...]]} 或 None(多价目时给出)} """ iface, product, err = await self._get_product_interface( product_id, product_code) diff --git a/wwwroot/storefront/index.ui b/wwwroot/storefront/index.ui index 53b740b..3a3a6b1 100644 --- a/wwwroot/storefront/index.ui +++ b/wwwroot/storefront/index.ui @@ -162,12 +162,33 @@ }, {% else %} {% if price_table %} -{# 多价目:表格展示(要素列+价格列),产线包月/包年、模型分辨率×类型分档都走这里 #} +{# 多价目:声明式表格(2026-09-18 用户纠正:不用 Html 拼 table,用 bricks 控件; + 行类 tabular-header-row/tabular-row 框架双主题齐备;数据走 otext+i18n 回退原文) #} { - "widgettype": "Html", - "options": { - "html": {{json.dumps(price_table.html, ensure_ascii=False)}} - } + "widgettype": "VBox", + "options": {"width": "100%", "gap": "0"}, + "subwidgets": [ + { + "widgettype": "HBox", + "options": {"css": "tabular-header-row", "width": "100%"}, + "subwidgets": [ +{% for h in price_table.headers %} + {"widgettype": "Text", "options": {"otext": {{json.dumps(h, ensure_ascii=False)}}, "text": {{json.dumps(h, ensure_ascii=False)}}, "i18n": true, "halign": "left", "css": "filler", "cfontsize": 0.75}}{{ "," if not loop.last }} +{% endfor %} + ] + }{{ "," if price_table.rows }} +{% for row in price_table.rows %} + { + "widgettype": "HBox", + "options": {"css": "tabular-row", "width": "100%"}, + "subwidgets": [ +{% for c in row %} + {"widgettype": "Text", "options": {"otext": {{json.dumps(c.t, ensure_ascii=False)}}, "text": {{json.dumps(c.t, ensure_ascii=False)}}, "i18n": true, "halign": "left", "css": "filler", "cfontsize": 0.75{% if c.k == 'price' %}, "color": "#e74c3c"{% elif c.k == 'orig' %}, "color": "var(--ink-3)", "textDecoration": "line-through"{% else %}, "color": "var(--ink-2)"{% endif %}}}{{ "," if not loop.last }} +{% endfor %} + ] + }{{ "," if not loop.last }} +{% endfor %} + ] }, {% else %} {