招标解析页面
This commit is contained in:
parent
62b8abc4a8
commit
a8b86d5f77
|
|
@ -212,7 +212,7 @@ export default {
|
|||
// 表格最大高度(像素),默认700px
|
||||
tableMaxHeight: {
|
||||
type: [Number, String],
|
||||
default: 700,
|
||||
default: 650,
|
||||
},
|
||||
// 是否自动加载数据 默认自动加载
|
||||
autoLoad: {
|
||||
|
|
|
|||
|
|
@ -52,14 +52,14 @@ import analysisResultMock from '../analysisResultMock.json'
|
|||
const HTML_TAG_REG = /<\/?[a-z][\s\S]*>/i
|
||||
const MAX_PARSE_DEPTH = 5
|
||||
|
||||
const formatSectionValue = (raw, depth = 0) => {
|
||||
const fallback = { content: '--', isHtml: false }
|
||||
function formatSectionValue(raw, depth = 0) {
|
||||
const fallback = { content: '--', isHtml: false, tableRows: null }
|
||||
if (raw === undefined || raw === null) {
|
||||
return fallback
|
||||
}
|
||||
if (depth > MAX_PARSE_DEPTH) {
|
||||
const content = String(raw)
|
||||
return { content, isHtml: HTML_TAG_REG.test(content) }
|
||||
return { content, isHtml: HTML_TAG_REG.test(content), tableRows: null }
|
||||
}
|
||||
if (typeof raw === 'string') {
|
||||
const trimmed = raw.trim()
|
||||
|
|
@ -70,10 +70,14 @@ const formatSectionValue = (raw, depth = 0) => {
|
|||
const parsed = JSON.parse(trimmed)
|
||||
return formatSectionValue(parsed, depth + 1)
|
||||
} catch (error) {
|
||||
return { content: trimmed, isHtml: HTML_TAG_REG.test(trimmed) }
|
||||
return { content: trimmed, isHtml: HTML_TAG_REG.test(trimmed), tableRows: null }
|
||||
}
|
||||
}
|
||||
if (Array.isArray(raw)) {
|
||||
const tableRows = buildTableRows(raw, depth)
|
||||
if (tableRows.length > 0) {
|
||||
return { content: '', isHtml: false, tableRows }
|
||||
}
|
||||
const lines = raw.map(item => {
|
||||
if (typeof item === 'object' && item !== null) {
|
||||
const label = item.name || item.label || item.title || item.key || ''
|
||||
|
|
@ -84,7 +88,7 @@ const formatSectionValue = (raw, depth = 0) => {
|
|||
return formatSectionValue(item, depth + 1).content
|
||||
}).filter(Boolean)
|
||||
const content = lines.length > 0 ? lines.join('\n') : '--'
|
||||
return { content, isHtml: false }
|
||||
return { content, isHtml: false, tableRows: null }
|
||||
}
|
||||
if (typeof raw === 'object') {
|
||||
if (Object.prototype.hasOwnProperty.call(raw, 'value')) {
|
||||
|
|
@ -95,10 +99,34 @@ const formatSectionValue = (raw, depth = 0) => {
|
|||
return `${key}:${formatted.content}`
|
||||
}).filter(Boolean)
|
||||
const content = lines.length > 0 ? lines.join('\n') : '--'
|
||||
return { content, isHtml: false }
|
||||
return { content, isHtml: false, tableRows: null }
|
||||
}
|
||||
const content = String(raw)
|
||||
return { content, isHtml: HTML_TAG_REG.test(content) }
|
||||
return { content, isHtml: HTML_TAG_REG.test(content), tableRows: null }
|
||||
}
|
||||
|
||||
function buildTableRows(items, depth) {
|
||||
const rows = items.map(item => {
|
||||
if (typeof item !== 'object' || item === null) {
|
||||
return null
|
||||
}
|
||||
const title = item.name ?? item.label ?? item.title ?? item.key ?? ''
|
||||
if (!title && title !== 0) {
|
||||
return null
|
||||
}
|
||||
const valueSource = item.content ?? item.value ?? item.text ?? item.desc ?? item.detail
|
||||
const formatted = formatSectionValue(valueSource, depth + 1)
|
||||
const nestedTable = formatted.tableRows && formatted.tableRows.length > 0
|
||||
? formatted.tableRows.map(row => `${row.title}:${row.value}`).join('\n')
|
||||
: ''
|
||||
const value = nestedTable || formatted.content || '--'
|
||||
return {
|
||||
title,
|
||||
value,
|
||||
isHtml: formatted.isHtml
|
||||
}
|
||||
}).filter(Boolean)
|
||||
return rows
|
||||
}
|
||||
|
||||
const collectSectionsFromNode = (node) => {
|
||||
|
|
@ -111,7 +139,8 @@ const collectSectionsFromNode = (node) => {
|
|||
id: target.id,
|
||||
title: target.name,
|
||||
content: formatted.content,
|
||||
isHtml: formatted.isHtml
|
||||
isHtml: formatted.isHtml,
|
||||
tableRows: formatted.tableRows
|
||||
})
|
||||
}
|
||||
if (target.children && target.children.length) {
|
||||
|
|
|
|||
|
|
@ -17,10 +17,33 @@
|
|||
<div class="content-section" v-for="section in subTab.sections"
|
||||
:key="section.id">
|
||||
<div class="section-title">{{ section.title }}</div>
|
||||
<template v-if="hasTable(section.tableRows)">
|
||||
<table class="section-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>标题</th>
|
||||
<th>内容</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="row in section.tableRows"
|
||||
:key="`${section.id}-${row.title}`">
|
||||
<td class="cell-title">{{ row.title }}</td>
|
||||
<td class="cell-value">
|
||||
<div v-if="!row.isHtml"
|
||||
v-html="formatPlainText(row.value)"></div>
|
||||
<div v-else v-html="row.value"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="section-content" v-if="!section.isHtml"
|
||||
v-html="formatPlainText(section.content)"></div>
|
||||
<div class="section-content html-content" v-else v-html="section.content">
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<div v-else class="empty-content">暂无数据</div>
|
||||
|
|
@ -33,9 +56,32 @@
|
|||
<template v-if="hasSections(tab.sections)">
|
||||
<div class="content-section" v-for="section in tab.sections" :key="section.id">
|
||||
<div class="section-title">{{ section.title }}</div>
|
||||
<template v-if="hasTable(section.tableRows)">
|
||||
<table class="section-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>标题</th>
|
||||
<th>内容</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="row in section.tableRows"
|
||||
:key="`${section.id}-${row.title}`">
|
||||
<td class="cell-title">{{ row.title }}</td>
|
||||
<td class="cell-value">
|
||||
<div v-if="!row.isHtml"
|
||||
v-html="formatPlainText(row.value)"></div>
|
||||
<div v-else v-html="row.value"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="section-content" v-if="!section.isHtml"
|
||||
v-html="formatPlainText(section.content)"></div>
|
||||
<div class="section-content html-content" v-else v-html="section.content"></div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<div v-else class="empty-content">暂无数据</div>
|
||||
|
|
@ -57,10 +103,33 @@
|
|||
<div class="content-section" v-for="section in subTab.sections"
|
||||
:key="section.id">
|
||||
<div class="section-title">{{ section.title }}</div>
|
||||
<template v-if="hasTable(section.tableRows)">
|
||||
<table class="section-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>标题</th>
|
||||
<th>内容</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="row in section.tableRows"
|
||||
:key="`${section.id}-${row.title}`">
|
||||
<td class="cell-title">{{ row.title }}</td>
|
||||
<td class="cell-value">
|
||||
<div v-if="!row.isHtml"
|
||||
v-html="formatPlainText(row.value)"></div>
|
||||
<div v-else v-html="row.value"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="section-content" v-if="!section.isHtml"
|
||||
v-html="formatPlainText(section.content)"></div>
|
||||
<div class="section-content html-content" v-else
|
||||
v-html="section.content"></div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<div v-else class="empty-content">暂无数据</div>
|
||||
|
|
@ -73,10 +142,34 @@
|
|||
<template v-if="hasSections(tab.sections)">
|
||||
<div class="content-section" v-for="section in tab.sections" :key="section.id">
|
||||
<div class="section-title">{{ section.title }}</div>
|
||||
<template v-if="hasTable(section.tableRows)">
|
||||
<table class="section-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>标题</th>
|
||||
<th>内容</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="row in section.tableRows"
|
||||
:key="`${section.id}-${row.title}`">
|
||||
<td class="cell-title">{{ row.title }}</td>
|
||||
<td class="cell-value">
|
||||
<div v-if="!row.isHtml"
|
||||
v-html="formatPlainText(row.value)"></div>
|
||||
<div v-else v-html="row.value"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="section-content" v-if="!section.isHtml"
|
||||
v-html="formatPlainText(section.content)"></div>
|
||||
<div class="section-content html-content" v-else v-html="section.content">
|
||||
<div class="section-content html-content" v-else
|
||||
v-html="section.content">
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<div v-else class="empty-content">暂无数据</div>
|
||||
|
|
@ -193,6 +286,9 @@ export default {
|
|||
hasSections(sections) {
|
||||
return Array.isArray(sections) && sections.length > 0
|
||||
},
|
||||
hasTable(rows) {
|
||||
return Array.isArray(rows) && rows.length > 0
|
||||
},
|
||||
formatPlainText(text) {
|
||||
if (!text) {
|
||||
return '--'
|
||||
|
|
@ -404,7 +500,7 @@ export default {
|
|||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding: 20px;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.el-tab-pane {
|
||||
|
|
@ -416,8 +512,7 @@ export default {
|
|||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
// padding: 20px;
|
||||
padding: 20px 0;
|
||||
padding: 20px;
|
||||
|
||||
.empty-content {
|
||||
text-align: center;
|
||||
|
|
@ -458,5 +553,38 @@ export default {
|
|||
border: 1px solid #EBEEF5;
|
||||
}
|
||||
}
|
||||
|
||||
.section-table {
|
||||
width: 100%;
|
||||
border: 1px solid #EBEEF5;
|
||||
border-collapse: collapse;
|
||||
font-size: 14px;
|
||||
background: #FFFFFF;
|
||||
|
||||
th,
|
||||
td {
|
||||
border: 1px solid #EBEEF5;
|
||||
padding: 12px 16px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
th {
|
||||
background: #FAFBFF;
|
||||
color: #909399;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.cell-title {
|
||||
width: 180px;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.cell-value {
|
||||
color: #606266;
|
||||
word-break: break-word;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue