Files
ONE-OS/web端/台账数据/车辆氢费明细-需求渲染.js
王冕 0898df3980 feat(web): 新增车辆氢费明细台账页面及需求文档
包含氢费录入、保存对账、筛选导入导出、异常标黄与需求明细弹窗等功能原型。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-21 16:57:18 +08:00

337 lines
6.5 KiB
JavaScript

/** 将 PRD Markdown 排版为 React 节点(车辆氢费明细) */
function parsePrdInlineText(text) {
var parts = String(text || '').split(/(\*\*[^*]+\*\*)/g);
var nodes = [];
var i;
for (i = 0; i < parts.length; i++) {
var p = parts[i];
if (!p) continue;
if (p.indexOf('**') === 0 && p.lastIndexOf('**') === p.length - 2) {
nodes.push(
React.createElement('strong', { key: i }, p.slice(2, -2))
);
} else {
nodes.push(p);
}
}
return nodes.length === 1 ? nodes[0] : nodes;
}
function isPrdTableRow(line) {
return /^\|.+\|$/.test(String(line || '').trim());
}
function isPrdTableSep(line) {
return /^\|[\s\-:|]+\|$/.test(String(line || '').trim());
}
function renderPrdTableRow(line, rowKey, isHeader) {
var cells = String(line)
.trim()
.replace(/^\|/, '')
.replace(/\|$/, '')
.split('|')
.map(function (c) {
return c.trim();
});
return React.createElement(
'tr',
{ key: rowKey },
cells.map(function (cell, ci) {
var Tag = isHeader ? 'th' : 'td';
return React.createElement(
Tag,
{
key: ci,
style: {
border: '1px solid #e5e7eb',
padding: '8px 10px',
textAlign: 'left',
verticalAlign: 'top',
fontWeight: isHeader ? 600 : 400,
background: isHeader ? '#f8fafc' : '#fff',
fontSize: 13,
lineHeight: 1.5
}
},
parsePrdInlineText(cell)
);
})
);
}
function renderPrdMarkdown(markdown) {
var lines = String(markdown || '').split(/\r?\n/);
var nodes = [];
var i = 0;
var inCode = false;
var codeBuf = [];
while (i < lines.length) {
var line = lines[i];
var trimmed = String(line || '').trim();
if (trimmed.indexOf('```') === 0) {
if (inCode) {
nodes.push(
React.createElement(
'pre',
{
key: 'code-' + i,
style: {
margin: '12px 0',
padding: '12px 14px',
background: '#f6f8fa',
border: '1px solid #e5e7eb',
borderRadius: 8,
fontSize: 12,
lineHeight: 1.6,
overflow: 'auto',
color: '#334155',
whiteSpace: 'pre-wrap'
}
},
codeBuf.join('\n')
)
);
codeBuf = [];
inCode = false;
} else {
inCode = true;
}
i += 1;
continue;
}
if (inCode) {
codeBuf.push(line);
i += 1;
continue;
}
if (trimmed === '---') {
nodes.push(
React.createElement('hr', {
key: 'hr-' + i,
style: { border: 'none', borderTop: '1px solid #e8ecf0', margin: '20px 0' }
})
);
i += 1;
continue;
}
if (isPrdTableRow(trimmed)) {
var tableLines = [];
while (i < lines.length && isPrdTableRow(String(lines[i]).trim())) {
tableLines.push(String(lines[i]).trim());
i += 1;
}
var bodyRows = [];
var ti;
for (ti = 0; ti < tableLines.length; ti++) {
if (isPrdTableSep(tableLines[ti])) continue;
bodyRows.push(
renderPrdTableRow(tableLines[ti], 'tr-' + i + '-' + ti, ti === 0)
);
}
if (bodyRows.length) {
nodes.push(
React.createElement(
'div',
{
key: 'tbl-' + i,
style: { overflowX: 'auto', margin: '12px 0 16px' }
},
React.createElement(
'table',
{
style: {
width: '100%',
borderCollapse: 'collapse',
fontSize: 13
}
},
React.createElement('tbody', null, bodyRows)
)
)
);
}
continue;
}
if (!trimmed) {
i += 1;
continue;
}
if (trimmed.indexOf('# ') === 0) {
nodes.push(
React.createElement(
'h1',
{
key: 'h1-' + i,
style: {
fontSize: 20,
fontWeight: 700,
color: '#0f172a',
margin: '0 0 16px',
lineHeight: 1.35
}
},
parsePrdInlineText(trimmed.slice(2).trim())
)
);
i += 1;
continue;
}
if (trimmed.indexOf('## ') === 0) {
nodes.push(
React.createElement(
'h2',
{
key: 'h2-' + i,
style: {
fontSize: 16,
fontWeight: 700,
color: '#1e293b',
margin: '24px 0 12px',
paddingBottom: 6,
borderBottom: '2px solid #e0f2fe',
lineHeight: 1.4
}
},
parsePrdInlineText(trimmed.slice(3).trim())
)
);
i += 1;
continue;
}
if (trimmed.indexOf('### ') === 0) {
nodes.push(
React.createElement(
'h3',
{
key: 'h3-' + i,
style: {
fontSize: 14,
fontWeight: 600,
color: '#334155',
margin: '16px 0 8px',
lineHeight: 1.45
}
},
parsePrdInlineText(trimmed.slice(4).trim())
)
);
i += 1;
continue;
}
if (trimmed === '**文档结束**') {
nodes.push(
React.createElement(
'div',
{
key: 'end-' + i,
style: {
marginTop: 24,
paddingTop: 16,
borderTop: '1px dashed #e2e8f0',
color: '#94a3b8',
fontSize: 13,
textAlign: 'center'
}
},
'— 文档结束 —'
)
);
i += 1;
continue;
}
if (/^\d+\.\s/.test(trimmed)) {
nodes.push(
React.createElement(
'div',
{
key: 'ol-' + i,
style: {
fontSize: 13,
color: '#475569',
lineHeight: 1.75,
margin: '6px 0 6px 4px',
paddingLeft: 4
}
},
parsePrdInlineText(trimmed)
)
);
i += 1;
continue;
}
if (trimmed.indexOf('- ') === 0) {
nodes.push(
React.createElement(
'div',
{
key: 'ul-' + i,
style: {
display: 'flex',
gap: 8,
fontSize: 13,
color: '#475569',
lineHeight: 1.75,
margin: '4px 0 4px 2px'
}
},
React.createElement('span', { style: { color: '#1677ff', flexShrink: 0 } }, '•'),
React.createElement('span', { style: { flex: 1 } }, parsePrdInlineText(trimmed.slice(2).trim()))
)
);
i += 1;
continue;
}
nodes.push(
React.createElement(
'p',
{
key: 'p-' + i,
style: {
fontSize: 13,
color: '#475569',
lineHeight: 1.75,
margin: '6px 0'
}
},
parsePrdInlineText(trimmed)
)
);
i += 1;
}
return nodes;
}
function renderH2RequirementDocPanel() {
var md =
typeof H2_LEDGER_REQUIREMENT_DOC !== 'undefined' && H2_LEDGER_REQUIREMENT_DOC
? H2_LEDGER_REQUIREMENT_DOC
: '';
if (!md) {
return React.createElement(
'div',
{ style: { padding: 24, color: '#64748b', textAlign: 'center' } },
'需求文档未加载,请确认已引入同目录文件:车辆氢费明细-需求内容.js'
);
}
return React.createElement(
'div',
{ className: 'h2-req-doc-panel', style: { padding: '4px 4px 16px' } },
renderPrdMarkdown(md)
);
}