重构 expense_claims 服务模块结构并优化差旅票据审核逻辑, 增强用户代理服务的票据类型识别,前端报销创建页面拆分为 附件模型和会话模型模块,重构提交编排器和草稿关联确认流 程,更新知识库索引,补充单元测试。
84 lines
2.4 KiB
JavaScript
84 lines
2.4 KiB
JavaScript
import MarkdownIt from 'markdown-it'
|
||
|
||
const markdown = new MarkdownIt({
|
||
html: false,
|
||
linkify: true,
|
||
breaks: true
|
||
})
|
||
|
||
const defaultTableOpen = markdown.renderer.rules.table_open
|
||
const defaultTableClose = markdown.renderer.rules.table_close
|
||
|
||
markdown.renderer.rules.table_open = (tokens, idx, options, env, self) => (
|
||
`<div class="markdown-table-wrap">${defaultTableOpen ? defaultTableOpen(tokens, idx, options, env, self) : '<table>'}`
|
||
)
|
||
|
||
markdown.renderer.rules.table_close = (tokens, idx, options, env, self) => (
|
||
`${defaultTableClose ? defaultTableClose(tokens, idx, options, env, self) : '</table>'}</div>`
|
||
)
|
||
|
||
const ALLOWED_COLON_HEADING_TITLES = new Set([
|
||
'基础信息识别结果',
|
||
'报销测算参考',
|
||
'补充信息'
|
||
])
|
||
|
||
function splitColonHeadingLine(line) {
|
||
const rawLine = String(line || '')
|
||
const trimmed = rawLine.trim()
|
||
if (!trimmed || trimmed.startsWith('|') || /^#{1,6}\s/.test(trimmed)) {
|
||
return [rawLine]
|
||
}
|
||
|
||
const chineseColonIndex = trimmed.indexOf(':')
|
||
const asciiColonIndex = trimmed.indexOf(':')
|
||
const colonIndexes = [chineseColonIndex, asciiColonIndex].filter((index) => index > 0)
|
||
if (!colonIndexes.length) {
|
||
return [rawLine]
|
||
}
|
||
|
||
const colonIndex = Math.min(...colonIndexes)
|
||
const title = trimmed.slice(0, colonIndex + 1)
|
||
const titleText = title.slice(0, -1)
|
||
const body = trimmed.slice(colonIndex + 1).trim()
|
||
if (!ALLOWED_COLON_HEADING_TITLES.has(titleText)) {
|
||
return [rawLine]
|
||
}
|
||
|
||
return body ? [`### ${title}`, '', body] : [`### ${title}`]
|
||
}
|
||
|
||
function normalizeColonHeadings(text) {
|
||
const lines = String(text || '').replace(/\r\n?/g, '\n').split('\n')
|
||
const normalizedLines = []
|
||
let inFence = false
|
||
|
||
lines.forEach((line) => {
|
||
if (/^\s*(```|~~~)/.test(line)) {
|
||
inFence = !inFence
|
||
normalizedLines.push(line)
|
||
return
|
||
}
|
||
if (inFence) {
|
||
normalizedLines.push(line)
|
||
return
|
||
}
|
||
|
||
const nextLines = splitColonHeadingLine(line)
|
||
if (nextLines[0]?.startsWith('### ') && normalizedLines.length) {
|
||
const previousLine = normalizedLines[normalizedLines.length - 1]
|
||
if (String(previousLine || '').trim()) {
|
||
normalizedLines.push('')
|
||
}
|
||
}
|
||
normalizedLines.push(...nextLines)
|
||
})
|
||
|
||
return normalizedLines.join('\n').replace(/\n{3,}/g, '\n\n')
|
||
}
|
||
|
||
export function renderMarkdown(text = '') {
|
||
const normalized = normalizeColonHeadings(text).trim()
|
||
return normalized ? markdown.render(normalized) : ''
|
||
}
|