refactor(storefront): 价格表去HTML化改bricks声明式控件(用户2026-09-18纠正:不用Html拼table)——core.py只回结构化headers/rows(单元格{t,k}),index.ui用VBox/HBox+Text(tabular-header-row/tabular-row框架双主题类)渲染,价格红/原价划线var(--ink-3)+line-through;Jinja真渲染验JSON合法

This commit is contained in:
yumoqing 2026-09-18 16:37:52 +08:00
parent 637c729e90
commit aee498de78
2 changed files with 38 additions and 36 deletions

View File

@ -1321,8 +1321,8 @@ class ProductManager:
全表同因子 flat=按次时省略价格列单位/已表达口径
Returns:
{'headers': [...], 'rows': [[要素值..., 价格文本]], 'html': '<table>…'}
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 = ['<table style="border-collapse:collapse;width:100%;'
'font-size:11px;line-height:1.5;">']
# 主题感知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('<tr>' + ''.join(
'<th style="%s">%s</th>' % (th_style, _html_escape(str(h)))
for h in headers) + '</tr>')
# 结构化返回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 = ('<span style="color:#e74c3c;font-weight:600;">%s</span>'
% _html_escape('¥%.4g %s' % (
p['amount'], p.get('unit_label') or '')))
if discount < 1.0 - 1e-9:
price_html += (' <span style="color:#94a3b8;text-decoration:'
'line-through;"%.4g</span>' % p['original_price'])
html.append('<tr>' + ''.join(
'<td style="%s">%s</td>' % (td_style, _html_escape(v))
for v in vals)
+ '<td style="%s">%s</td></tr>' % (td_style, price_html))
html.append('</table>')
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)

View File

@ -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 %}
{