Files
leaudit-platform-frontend/html/renderText(2).html
T

1693 lines
56 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>renderText 增强型文本渲染器</title>
<link rel="stylesheet" href="https://unpkg.com/tailwindcss@2.2.19/dist/tailwind.min.css">
<link href="https://unpkg.com/remixicon@2.5.0/fonts/remixicon.css" rel="stylesheet">
<script src="https://unpkg.com/marked@4.3.0/marked.min.js"></script>
<style>
:root {
--primary-color: #2563eb;
--primary-hover: #1d4ed8;
--secondary-color: #64748b;
--light-bg: #f8fafc;
--dark-bg: #1e293b;
--success: #22c55e;
--warning: #f59e0b;
--error: #ef4444;
--info: #3b82f6;
}
body {
font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
color: #334155;
line-height: 1.5;
}
.tag {
display: inline-block;
padding: 0.25rem 0.75rem;
margin-right: 0.5rem;
margin-bottom: 0.5rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
background-color: #e2e8f0;
color: #475569;
transition: background-color 0.3s, color 0.3s;
}
.tag.data {
background-color: #dbeafe;
color: #2563eb;
}
.tag:hover {
filter: brightness(0.95);
}
.code-block {
position: relative;
background-color: #f1f5f9;
border-radius: 0.5rem;
font-family: 'Fira Code', monospace;
font-size: 0.875rem;
overflow-x: auto;
margin-bottom: 1.5rem;
}
.code-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.75rem 1rem;
background-color: #e2e8f0;
border-top-left-radius: 0.5rem;
border-top-right-radius: 0.5rem;
font-size: 0.875rem;
font-weight: 600;
}
.code-content {
padding: 1rem;
overflow-x: auto;
}
.copy-btn {
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
background-color: #cbd5e1;
color: #475569;
font-size: 0.75rem;
font-weight: 500;
cursor: pointer;
transition: background-color 0.3s, color 0.3s;
}
.copy-btn:hover {
background-color: #94a3b8;
color: #1e293b;
}
.preview-block {
margin-top: 1rem;
padding: 1rem;
background-color: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 0.5rem;
}
.section-title {
display: flex;
align-items: center;
margin-bottom: 1rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid #e2e8f0;
}
.section-title i {
margin-right: 0.5rem;
color: var(--primary-color);
}
.param-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 1.5rem;
}
.param-table th, .param-table td {
padding: 0.75rem 1rem;
border: 1px solid #e2e8f0;
text-align: left;
}
.param-table th {
background-color: #f1f5f9;
font-weight: 600;
}
.param-table tr:nth-child(even) {
background-color: #f8fafc;
}
.preview-title {
margin-bottom: 0.5rem;
font-weight: 600;
color: #64748b;
}
/* 增强的Tooltip样式 */
.tooltip-trigger {
position: relative;
display: inline-block;
cursor: pointer;
border-bottom: 1px dotted #64748b;
}
.tooltip-container {
position: absolute;
visibility: hidden;
opacity: 0;
z-index: 100;
width: max-content;
max-width: 320px;
transition: opacity 0.3s ease;
pointer-events: none;
}
.tooltip-trigger:hover .tooltip-container {
visibility: visible;
opacity: 1;
pointer-events: auto;
}
.tooltip-content {
position: relative;
padding: 0.75rem 1rem;
border-radius: 0.375rem;
font-size: 0.875rem;
line-height: 1.5;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.tooltip-arrow {
position: absolute;
width: 0;
height: 0;
border-style: solid;
}
/* Tooltip主题 */
.tooltip-dark .tooltip-content {
background-color: #1e293b;
color: #f1f5f9;
}
.tooltip-dark .tooltip-arrow {
border-color: #1e293b;
}
.tooltip-light .tooltip-content {
background-color: #ffffff;
color: #334155;
border: 1px solid #e2e8f0;
}
.tooltip-light .tooltip-arrow {
border-color: #ffffff;
}
.tooltip-primary .tooltip-content {
background-color: var(--primary-color);
color: #ffffff;
}
.tooltip-primary .tooltip-arrow {
border-color: var(--primary-color);
}
.tooltip-success .tooltip-content {
background-color: var(--success);
color: #ffffff;
}
.tooltip-success .tooltip-arrow {
border-color: var(--success);
}
.tooltip-warning .tooltip-content {
background-color: var(--warning);
color: #ffffff;
}
.tooltip-warning .tooltip-arrow {
border-color: var(--warning);
}
.tooltip-error .tooltip-content {
background-color: var(--error);
color: #ffffff;
}
.tooltip-error .tooltip-arrow {
border-color: var(--error);
}
/* Info主题样式 */
.tooltip-info .tooltip-content {
background-color: var(--info);
color: #ffffff;
}
.tooltip-info .tooltip-arrow {
border-color: var(--info);
}
/* Tooltip位置 - 移除固定的transform,使用JS动态计算位置 */
.tooltip-top {
bottom: calc(100% + 5px);
}
.tooltip-top .tooltip-arrow {
bottom: -8px;
border-width: 8px 8px 0 8px;
border-color: inherit transparent transparent transparent;
}
.tooltip-bottom {
top: calc(100% + 5px);
}
.tooltip-bottom .tooltip-arrow {
top: -8px;
border-width: 0 8px 8px 8px;
border-color: transparent transparent inherit transparent;
}
.tooltip-left {
right: calc(100% + 5px);
top: 50%;
transform: translateY(-50%);
}
.tooltip-left .tooltip-arrow {
right: -8px;
top: 50%;
margin-top: -8px;
border-width: 8px 0 8px 8px;
border-color: transparent transparent transparent inherit;
}
.tooltip-right {
left: calc(100% + 5px);
top: 50%;
transform: translateY(-50%);
}
.tooltip-right .tooltip-arrow {
left: -8px;
top: 50%;
margin-top: -8px;
border-width: 8px 8px 8px 0;
border-color: transparent inherit transparent transparent;
}
/* Tooltip增强风格 */
.tooltip-rich .tooltip-content {
padding: 0;
overflow: hidden;
}
.tooltip-header {
padding: 0.5rem 1rem;
font-weight: 600;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.tooltip-body {
padding: 0.75rem 1rem;
}
.tooltip-footer {
padding: 0.5rem 1rem;
background-color: rgba(0, 0, 0, 0.05);
border-top: 1px solid rgba(255, 255, 255, 0.1);
font-size: 0.75rem;
text-align: right;
}
/* 复制成功提示样式 */
.copy-success-tooltip {
position: absolute;
background-color: rgba(34, 197, 94, 0.9);
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 0.75rem;
z-index: 1000;
white-space: nowrap;
pointer-events: none;
transform: translateY(-100%);
top: -8px;
left: 50%;
margin-left: -24px;
opacity: 0;
transition: opacity 0.3s ease, transform 0.3s ease;
}
.copy-success-tooltip.show {
opacity: 1;
transform: translateY(-120%);
}
.copy-success-tooltip::after {
content: '';
position: absolute;
top: 100%;
left: 50%;
margin-left: -4px;
border-width: 4px;
border-style: solid;
border-color: rgba(34, 197, 94, 0.9) transparent transparent transparent;
}
/* 使复制图标相对定位,以便定位漂浮提示 */
.copy-phone-btn {
position: relative;
}
/* Tooltip表格样式优化 */
.tooltip-content table {
border-collapse: collapse;
width: 100%;
font-size: 0.75rem;
}
.tooltip-content table th,
.tooltip-content table td {
padding: 0.25rem 0.5rem;
text-align: left;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
.tooltip-content table th {
font-weight: 600;
background-color: rgba(0, 0, 0, 0.05);
}
.tooltip-content table tr:nth-child(even) {
background-color: rgba(0, 0, 0, 0.02);
}
/* 深色主题下的表格样式 */
.tooltip-dark .tooltip-content table th,
.tooltip-dark .tooltip-content table td {
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.tooltip-dark .tooltip-content table th {
background-color: rgba(255, 255, 255, 0.1);
}
.tooltip-dark .tooltip-content table tr:nth-child(even) {
background-color: rgba(255, 255, 255, 0.05);
}
/* Markdown表格容器样式 */
.markdown-table {
font-size: 0.75rem;
line-height: 1.4;
}
.markdown-table table {
width: 100%;
border-collapse: collapse;
margin: 0;
}
.markdown-table th,
.markdown-table td {
padding: 0.25rem 0.5rem;
text-align: left;
vertical-align: top;
}
.markdown-table th {
font-weight: 600;
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
}
.markdown-table td {
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
/* 深色主题下的markdown表格 */
.tooltip-dark .markdown-table th {
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}
.tooltip-dark .markdown-table td {
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
/* Markdown渲染内容样式 */
.markdown-content {
font-size: 0.75rem;
line-height: 1.4;
}
.markdown-content table {
width: 100%;
border-collapse: collapse;
margin: 0;
}
.markdown-content th,
.markdown-content td {
padding: 0.25rem 0.5rem;
text-align: left;
vertical-align: top;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
.markdown-content th {
font-weight: 600;
background-color: rgba(0, 0, 0, 0.05);
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
}
.markdown-content tr:nth-child(even) {
background-color: rgba(0, 0, 0, 0.02);
}
/* 深色主题下的markdown内容 */
.tooltip-dark .markdown-content th,
.tooltip-dark .markdown-content td {
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.tooltip-dark .markdown-content th {
background-color: rgba(255, 255, 255, 0.1);
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}
.tooltip-dark .markdown-content tr:nth-child(even) {
background-color: rgba(255, 255, 255, 0.05);
}
/* 通用的markdown渲染表格样式 */
.markdown-rendered-table {
width: 100%;
border-collapse: collapse;
font-size: 0.75rem;
}
.markdown-rendered-table th,
.markdown-rendered-table td {
padding: 0.25rem 0.5rem;
text-align: left;
vertical-align: top;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
.markdown-rendered-table th {
font-weight: 600;
background-color: rgba(0, 0, 0, 0.05);
}
.markdown-rendered-table tbody tr:nth-child(even) {
background-color: rgba(0, 0, 0, 0.02);
}
/* 深色主题下的markdown渲染表格 */
.tooltip-dark .markdown-rendered-table th,
.tooltip-dark .markdown-rendered-table td {
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.tooltip-dark .markdown-rendered-table th {
background-color: rgba(255, 255, 255, 0.1);
}
.tooltip-dark .markdown-rendered-table tbody tr:nth-child(even) {
background-color: rgba(255, 255, 255, 0.05);
}
</style>
</head>
<body>
<div class="container mx-auto px-4 py-8">
<main class="flex-1">
<!-- renderText -->
<div id="renderText" class="renderer-section">
<div class="section-title">
<i class="ri-text-line text-xl"></i>
<h3 class="text-2xl font-semibold">renderText 增强型文本渲染器</h3>
</div>
<div class="mb-4">
<span class="tag data">文本处理</span>
<span class="tag">样式增强</span>
<span class="tag">条件渲染</span>
<span class="tag">漂浮提示</span>
</div>
<p class="mb-4">renderText 增强型文本渲染器提供了全方位的文本展示解决方案,支持多种文本转换、格式化、条件样式和增强型漂浮提示,满足各种复杂场景的展示需求。</p>
<h4 class="text-lg font-semibold mb-2">API参数</h4>
<table class="param-table">
<thead>
<tr>
<th>参数名</th>
<th>类型</th>
<th>描述</th>
<th>是否必填</th>
<th>默认值</th>
</tr>
</thead>
<tbody>
<tr>
<td>transform</td>
<td>String</td>
<td>文本转换类型:uppercase/lowercase/capitalize</td>
<td></td>
<td>-</td>
</tr>
<tr>
<td>format</td>
<td>String</td>
<td>特定格式处理:phone/idcard/bankcard/date/number</td>
<td></td>
<td>-</td>
</tr>
<tr>
<td>prefix</td>
<td>String</td>
<td>文本前缀</td>
<td></td>
<td>-</td>
</tr>
<tr>
<td>suffix</td>
<td>String</td>
<td>文本后缀</td>
<td></td>
<td>-</td>
</tr>
<tr>
<td>nullValue</td>
<td>String</td>
<td>空值显示文本</td>
<td></td>
<td>"-"</td>
</tr>
<tr>
<td>maxLength</td>
<td>Number</td>
<td>最大显示长度</td>
<td></td>
<td>-</td>
</tr>
<tr>
<td>ellipsis</td>
<td>Boolean</td>
<td>是否显示省略号</td>
<td></td>
<td>true</td>
</tr>
<tr>
<td>tooltip</td>
<td>Boolean</td>
<td>是否启用悬浮提示</td>
<td></td>
<td>false</td>
</tr>
<tr>
<td>tooltipProps</td>
<td>Object</td>
<td>悬浮提示配置</td>
<td></td>
<td>-</td>
</tr>
<tr>
<td class="tooltip-trigger">
tooltipProps.theme
<div class="tooltip-container tooltip-top tooltip-primary">
<div class="tooltip-content">
<div>可选值: dark、light、primary、success、warning、error</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</td>
<td>String</td>
<td>提示框主题</td>
<td></td>
<td>"dark"</td>
</tr>
<tr>
<td class="tooltip-trigger">
tooltipProps.placement
<div class="tooltip-container tooltip-top tooltip-primary">
<div class="tooltip-content">
<div>可选值: top、bottom、left、right</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</td>
<td>String</td>
<td>提示框位置</td>
<td></td>
<td>"top"</td>
</tr>
<tr>
<td>tooltipProps.content</td>
<td>String</td>
<td>提示内容</td>
<td></td>
<td>-</td>
</tr>
<tr>
<td>tooltipProps.rich</td>
<td>Boolean</td>
<td>是否使用富文本提示</td>
<td></td>
<td>false</td>
</tr>
<tr>
<td>tooltipProps.header</td>
<td>String</td>
<td>富文本提示标题</td>
<td></td>
<td>-</td>
</tr>
<tr>
<td>tooltipProps.footer</td>
<td>String</td>
<td>富文本提示页脚</td>
<td></td>
<td>-</td>
</tr>
<tr>
<td>highlight</td>
<td>Object</td>
<td>高亮配置</td>
<td></td>
<td>-</td>
</tr>
<tr>
<td>conditional</td>
<td>Array</td>
<td>条件样式规则</td>
<td></td>
<td>-</td>
</tr>
<tr>
<td>copyable</td>
<td>Boolean</td>
<td>是否可复制</td>
<td></td>
<td>false</td>
</tr>
<tr>
<td>link</td>
<td>Boolean/Object</td>
<td>转为链接</td>
<td></td>
<td>false</td>
</tr>
</tbody>
</table>
<h4 class="text-lg font-semibold mb-2">使用示例</h4>
<div class="code-block">
<div class="code-header">
<span>基本使用 - 文本转换</span>
<button class="copy-btn">复制</button>
</div>
<div class="code-content">
<pre>{
"id": "title",
"label": "标题",
"dataIndex": "title",
"render": "renderText",
"renderProps": {
"transform": "capitalize",
"nullValue": "无标题"
}
}</pre>
</div>
</div>
<div class="code-block">
<div class="code-header">
<span>数据脱敏</span>
<button class="copy-btn">复制</button>
</div>
<div class="code-content">
<pre>{
"id": "phone",
"label": "手机号",
"dataIndex": "phone",
"render": "renderText",
"renderProps": {
"format": "phone",
"copyable": true
}
}</pre>
</div>
</div>
<div class="code-block">
<div class="code-header">
<span>带前缀后缀</span>
<button class="copy-btn">复制</button>
</div>
<div class="code-content">
<pre>{
"id": "price",
"label": "价格",
"dataIndex": "price",
"render": "renderText",
"renderProps": {
"prefix": "¥",
"suffix": "元",
"format": "number"
}
}</pre>
</div>
</div>
<div class="code-block">
<div class="code-header">
<span>链接转换</span>
<button class="copy-btn">复制</button>
</div>
<div class="code-content">
<pre>{
"id": "website",
"label": "网站",
"dataIndex": "website",
"render": "renderText",
"renderProps": {
"link": {
"target": "_blank",
"urlPrefix": "https://"
}
}
}</pre>
</div>
</div>
<div class="code-block">
<div class="code-header">
<span>基础悬浮提示</span>
<button class="copy-btn">复制</button>
</div>
<div class="code-content">
<pre>{
"id": "productDescription",
"label": "产品描述",
"dataIndex": "productDescription",
"render": "renderText",
"renderProps": {
"maxLength": 50,
"ellipsis": true,
"tooltip": true,
"tooltipProps": {
"placement": "top",
"theme": "dark",
"content": "data.productFullDescription"
}
}
}</pre>
</div>
</div>
<div class="code-block">
<div class="code-header">
<span>增强型悬浮提示框</span>
<button class="copy-btn">复制</button>
</div>
<div class="code-content">
<pre>{
"id": "stockInfo",
"label": "库存状态",
"dataIndex": "stockStatus",
"render": "renderText",
"renderProps": {
"tooltip": true,
"tooltipProps": {
"placement": "right",
"theme": "primary",
"rich": true,
"header": "库存详情",
"content": "data.stockDetail",
"footer": "更新时间: {{data.stockUpdateTime}}"
}
}
}</pre>
</div>
</div>
<div class="code-block">
<div class="code-header">
<span>增强型提示框 - 浅色主题</span>
<button class="copy-btn">复制</button>
</div>
<div class="code-content">
<pre>{
"id": "performance",
"label": "性能指标",
"dataIndex": "performance",
"render": "renderText",
"renderProps": {
"tooltip": true,
"tooltipProps": {
"placement": "top",
"theme": "light",
"rich": true,
"header": "系统性能报告",
"content": "data.performanceDetail",
"footer": "更新时间: {{data.updateTime}}"
},
"conditional": [
{ "condition": "data.status === 'normal'", "style": { "color": "#3b82f6", "fontWeight": "medium" } }
]
}
}</pre>
</div>
</div>
<div class="code-block">
<div class="code-header">
<span>增强型提示框 - 深色主题</span>
<button class="copy-btn">复制</button>
</div>
<div class="code-content">
<pre>{
"id": "salesTrend",
"label": "销售趋势",
"dataIndex": "salesTrend",
"render": "renderText",
"renderProps": {
"tooltip": true,
"tooltipProps": {
"placement": "bottom",
"theme": "dark",
"rich": true,
"header": "销售数据分析",
"content": "data.salesDetail",
"footer": "数据来源: 销售管理系统"
},
"conditional": [
{ "condition": "data.growth > 10", "style": { "color": "#22c55e", "fontWeight": "medium" } }
]
}
}</pre>
</div>
</div>
<div class="code-block">
<div class="code-header">
<span>表格格式悬浮提示</span>
<button class="copy-btn">复制</button>
</div>
<div class="code-content">
<pre>{
"id": "inventoryDetail",
"label": "库存详情",
"dataIndex": "inventoryStatus",
"render": "renderText",
"renderProps": {
"tooltip": true,
"tooltipProps": {
"placement": "top",
"theme": "light",
"rich": true,
"header": "卷烟库存明细表",
"content": "{{data.inventoryTableMarkdown}}",
"footer": "备注:卷烟真假待鉴定"
}
}
}</pre>
</div>
</div>
<div class="code-block">
<div class="code-header">
<span>条件样式</span>
<button class="copy-btn">复制</button>
</div>
<div class="code-content">
<pre>{
"id": "status",
"label": "订单状态",
"dataIndex": "status",
"render": "renderText",
"renderProps": {
"conditional": [
{ "condition": "value === '待处理'", "style": { "color": "#f59e0b" } },
{ "condition": "value === '处理中'", "style": { "color": "#3b82f6" } },
{ "condition": "value === '已完成'", "style": { "color": "#22c55e", "fontWeight": "bold" } },
{ "condition": "value === '已取消'", "style": { "color": "#ef4444" } }
]
}
}</pre>
</div>
</div>
<div class="code-block">
<div class="code-header">
<span>表格格式悬浮提示 - 深色主题</span>
<button class="copy-btn">复制</button>
</div>
<div class="code-content">
<pre>{
"id": "salesStatistics",
"label": "销售统计",
"dataIndex": "salesTrend",
"render": "renderText",
"renderProps": {
"tooltip": true,
"tooltipProps": {
"placement": "top",
"theme": "dark",
"rich": true,
"header": "月度销售统计表",
"content": "{{data.salesTableMarkdown}}",
"footer": "数据更新时间: {{data.updateTime}}"
}
}
}</pre>
</div>
</div>
<div class="code-block">
<div class="code-header">
<span>Markdown表格变量示例</span>
<button class="copy-btn">复制</button>
</div>
<div class="code-content">
<pre>// 数据源中的markdown表格变量示例
data: {
inventoryTableMarkdown: `
| 品种规格 | 单位 | 数量 | 品种规格 | 单位 | 数量 |
|----------------|------|------|----------------|------|------|
| 黄山(印象一品) | 条 | 75 | 以下空白 | | |
| 白沙(硬) | 条 | 174 | | | |
| 娇子(蓝时代) | 条 | 63 | | | |
| 黄山(新一品) | 条 | 220 | | | |
| 金圣(庐山) | 条 | 40 | | | |
| 钻石(硬特醇) | 条 | 342 | | | |
| 共计:(品种)6个 | | | 总计:(数量)914条 | | |
| 备注 | | | 卷烟真假待鉴定 | | |
`,
salesTableMarkdown: `
| 品种规格 | 单位 | 数量 | 品种规格 | 单位 | 数量 |
|----------------|------|------|----------------|------|------|
| 黄山(印象一品) | 条 | 75 | 以下空白 | | |
| 白沙(硬) | 条 | 174 | | | |
| 娇子(蓝时代) | 条 | 63 | | | |
| 黄山(新一品) | 条 | 220 | | | |
| 金圣(庐山) | 条 | 40 | | | |
| 钻石(硬特醇) | 条 | 342 | | | |
| 共计:(品种)6个 | | | 总计:(数量)914条 | | |
| 备注 | | | 卷烟真假待鉴定 | | |
`,
updateTime: "2023-10-15 16:30:42"
}</pre>
</div>
</div>
<div class="code-block">
<div class="code-header">
<span>实际项目中的Markdown渲染实现</span>
<button class="copy-btn">复制</button>
</div>
<div class="code-content">
<pre>// 方案一:使用Markdown解析库 (如 marked.js)
import { marked } from 'marked';
function renderTooltipContent(markdownContent) {
// 解析markdown为HTML
const htmlContent = marked.parse(markdownContent);
// 渲染到tooltip容器中
const tooltipBody = document.querySelector('.tooltip-body');
tooltipBody.innerHTML = htmlContent;
// 添加通用样式类
const table = tooltipBody.querySelector('table');
if (table) {
table.classList.add('markdown-rendered-table');
}
}
// 方案二:使用React Markdown组件
import ReactMarkdown from 'react-markdown';
function TooltipContent({ markdownContent }) {
return (
&lt;div className="tooltip-body"&gt;
&lt;ReactMarkdown
components={{
table: ({node, ...props}) =&gt;
&lt;table className="markdown-rendered-table" {...props} /&gt;
}}
&gt;
{markdownContent}
&lt;/ReactMarkdown&gt;
&lt;/div&gt;
);
}
// 方案三:使用Vue Markdown组件
&lt;template&gt;
&lt;div class="tooltip-body"&gt;
&lt;VueMarkdown
:source="markdownContent"
:table-class="'markdown-rendered-table'"
/&gt;
&lt;/div&gt;
&lt;/template&gt;
// 通用样式控制方案:通过CSS类和数据属性
.markdown-rendered-table {
/* 基础表格样式 */
}
.markdown-rendered-table[data-theme="dark"] {
/* 深色主题样式 */
}
.markdown-rendered-table[data-highlight="true"] {
/* 高亮样式 */
}
// 使用示例
const tooltipProps = {
placement: "top",
theme: "light",
rich: true,
header: "数据详情",
content: "{{data.tableMarkdown}}", // 动态markdown内容
footer: "更新时间: {{data.updateTime}}"
};</pre>
</div>
</div>
<h4 class="text-lg font-semibold mb-4">渲染效果</h4>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="preview-block">
<div class="preview-title">文本转换</div>
<div>原始数据:<code>"hello world"</code></div>
<div class="mt-2">渲染结果:<span class="text-sm">Hello World</span></div>
</div>
<div class="preview-block">
<div class="preview-title">电话脱敏</div>
<div>原始数据:<code>"13812345678"</code></div>
<div class="mt-2">渲染结果:<span class="text-sm">138****5678</span> <i class="ri-file-copy-line text-gray-400 text-xs cursor-pointer copy-phone-btn" data-value="13812345678" title="复制完整号码"></i></div>
</div>
<div class="preview-block">
<div class="preview-title">带前缀后缀</div>
<div>原始数据:<code>99.99</code></div>
<div class="mt-2">渲染结果:<span class="text-sm">¥99.99元</span></div>
</div>
<div class="preview-block">
<div class="preview-title">链接转换</div>
<div>原始数据:<code>"example.com"</code></div>
<div class="mt-2">渲染结果:<a href="https://example.com" target="_blank" class="text-blue-500 hover:underline">example.com</a></div>
</div>
<div class="preview-block">
<div class="preview-title">基础悬浮提示</div>
<div>原始数据:<code>"RapidCore是一个高效的低代码开发框架..."</code></div>
<div class="mt-2">渲染结果:
<span class="tooltip-trigger">
RapidCore是一个高效的低代码开发框架...
<div class="tooltip-container tooltip-top tooltip-dark">
<div class="tooltip-content">
<div>RapidCore是一个高效的低代码开发框架,可以帮助开发者快速构建企业级应用,提供了丰富的组件和灵活的配置选项,支持多种数据源和自定义扩展。</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</span>
</div>
</div>
<div class="preview-block">
<div class="preview-title">主题色提示框</div>
<div>原始数据:<code>"库存紧张"</code></div>
<div class="mt-2">渲染结果:
<span class="tooltip-trigger">
<span class="text-yellow-500">库存紧张</span>
<div class="tooltip-container tooltip-right tooltip-warning">
<div class="tooltip-content">
<div>当前库存仅剩5件,低于安全库存(10件),请及时补货</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</span>
</div>
</div>
<div class="preview-block">
<div class="preview-title">增强型提示框 - 浅色主题</div>
<div>原始数据:<code>"性能分析"</code></div>
<div class="mt-2">渲染结果:
<span class="tooltip-trigger">
<span class="text-blue-500 font-medium">性能分析</span>
<div class="tooltip-container tooltip-top tooltip-light tooltip-rich">
<div class="tooltip-content">
<div class="tooltip-header">系统性能报告</div>
<div class="tooltip-body">
<div class="flex items-center mb-1">
<span class="w-24 text-gray-500">CPU使用率:</span>
<span class="text-green-500 font-medium">32%</span>
</div>
<div class="flex items-center mb-1">
<span class="w-24 text-gray-500">内存使用率:</span>
<span class="text-yellow-500 font-medium">76%</span>
</div>
<div class="flex items-center">
<span class="w-24 text-gray-500">磁盘空间:</span>
<span class="text-blue-500 font-medium">245GB/500GB</span>
</div>
</div>
<div class="tooltip-footer">更新时间: 2023-10-15 15:30:42</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</span>
</div>
</div>
<div class="preview-block">
<div class="preview-title">增强型提示框 - 深色主题</div>
<div>原始数据:<code>"销售趋势"</code></div>
<div class="mt-2">渲染结果:
<span class="tooltip-trigger">
<span class="text-green-500 font-medium">销售趋势</span>
<div class="tooltip-container tooltip-bottom tooltip-dark tooltip-rich">
<div class="tooltip-content">
<div class="tooltip-header">销售数据分析</div>
<div class="tooltip-body">
<div class="flex items-center justify-between mb-1">
<span>本月销售额:</span>
<span class="text-green-400 font-medium">¥258,432</span>
</div>
<div class="flex items-center justify-between mb-1">
<span>环比增长:</span>
<span class="text-green-400 font-medium">+15.8%</span>
</div>
<div class="flex items-center justify-between">
<span>销售热点:</span>
<span class="text-yellow-400 font-medium">电子产品</span>
</div>
</div>
<div class="tooltip-footer">数据来源: 销售管理系统</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</span>
</div>
</div>
<div class="preview-block">
<div class="preview-title">条件样式</div>
<div>
<div>原始值:<code>"待处理"</code></div>
<div class="mt-1">渲染结果:
<span class="text-yellow-500">待处理</span>
</div>
</div>
<div class="mt-2">
<div>原始值:<code>"处理中"</code></div>
<div class="mt-1">渲染结果:
<span class="text-blue-500">处理中</span>
</div>
</div>
<div class="mt-2">
<div>原始值:<code>"已完成"</code></div>
<div class="mt-1">渲染结果:
<span class="text-green-500 font-bold">已完成</span>
</div>
</div>
<div class="mt-2">
<div>原始值:<code>"已取消"</code></div>
<div class="mt-1">渲染结果:
<span class="text-red-500">已取消</span>
</div>
</div>
</div>
<div class="preview-block">
<div class="preview-title">带条件的悬浮提示</div>
<div>原始值:<code>95</code></div>
<div class="mt-1">渲染结果:
<span class="tooltip-trigger">
<span class="text-green-500 font-bold">95</span>
<div class="tooltip-container tooltip-top tooltip-success">
<div class="tooltip-content">
<div>优秀:得分在90分以上</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</span>
</div>
<div class="mt-2">
<div>原始值:<code>75</code></div>
<div class="mt-1">渲染结果:
<span class="tooltip-trigger">
<span class="text-yellow-500">75</span>
<div class="tooltip-container tooltip-top tooltip-warning">
<div class="tooltip-content">
<div>良好:得分在60-90分之间</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</span>
</div>
</div>
</div>
<!-- 深色主题 -->
<div class="preview-block">
<div class="preview-title">深色主题 (Dark)</div>
<div>配置:<code>tooltipProps: { theme: "dark" }</code></div>
<div class="mt-2">渲染结果:
<span class="tooltip-trigger">
<span class="border-b border-dotted border-gray-500">深色主题</span>
<div class="tooltip-container tooltip-top tooltip-dark">
<div class="tooltip-content">
<div>这是深色主题提示框</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</span>
</div>
</div>
<!-- 浅色主题 -->
<div class="preview-block">
<div class="preview-title">浅色主题 (Light)</div>
<div>配置:<code>tooltipProps: { theme: "light" }</code></div>
<div class="mt-2">渲染结果:
<span class="tooltip-trigger">
<span class="border-b border-dotted border-gray-500">浅色主题</span>
<div class="tooltip-container tooltip-top tooltip-light">
<div class="tooltip-content">
<div>这是浅色主题提示框</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</span>
</div>
</div>
<!-- 主题色 -->
<div class="preview-block">
<div class="preview-title">主题色 (Primary)</div>
<div>配置:<code>tooltipProps: { theme: "primary" }</code></div>
<div class="mt-2">渲染结果:
<span class="tooltip-trigger">
<span class="border-b border-dotted border-gray-500">主题色</span>
<div class="tooltip-container tooltip-top tooltip-primary">
<div class="tooltip-content">
<div>这是主题色提示框</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</span>
</div>
</div>
<!-- 成功色 -->
<div class="preview-block">
<div class="preview-title">成功色 (Success)</div>
<div>配置:<code>tooltipProps: { theme: "success" }</code></div>
<div class="mt-2">渲染结果:
<span class="tooltip-trigger">
<span class="border-b border-dotted border-gray-500">成功色</span>
<div class="tooltip-container tooltip-top tooltip-success">
<div class="tooltip-content">
<div>这是成功色提示框</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</span>
</div>
</div>
<!-- 警告色 -->
<div class="preview-block">
<div class="preview-title">警告色 (Warning)</div>
<div>配置:<code>tooltipProps: { theme: "warning" }</code></div>
<div class="mt-2">渲染结果:
<span class="tooltip-trigger">
<span class="border-b border-dotted border-gray-500">警告色</span>
<div class="tooltip-container tooltip-top tooltip-warning">
<div class="tooltip-content">
<div>这是警告色提示框</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</span>
</div>
</div>
<!-- 错误色 -->
<div class="preview-block">
<div class="preview-title">错误色 (Error)</div>
<div>配置:<code>tooltipProps: { theme: "error" }</code></div>
<div class="mt-2">渲染结果:
<span class="tooltip-trigger">
<span class="border-b border-dotted border-gray-500">错误色</span>
<div class="tooltip-container tooltip-top tooltip-error">
<div class="tooltip-content">
<div>这是错误色提示框</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</span>
</div>
</div>
<!-- 信息色 -->
<div class="preview-block">
<div class="preview-title">信息色 (Info)</div>
<div>配置:<code>tooltipProps: { theme: "info" }</code></div>
<div class="mt-2">渲染结果:
<span class="tooltip-trigger">
<span class="border-b border-dotted border-gray-500">信息色</span>
<div class="tooltip-container tooltip-top tooltip-info">
<div class="tooltip-content">
<div>这是信息色提示框</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</span>
</div>
</div>
<!-- 表格格式悬浮提示 -->
<div class="preview-block">
<div class="preview-title">表格格式悬浮提示</div>
<div>配置:<code>tooltipProps: { placement: "top", theme: "light", rich: true }</code></div>
<div class="mt-2">
<div class="mb-2">
<strong>Markdown源码:</strong>
<div class="bg-gray-100 p-2 rounded text-xs font-mono">
| 品种规格 | 单位 | 数量 | 品种规格 | 单位 | 数量 |<br>
|----------|------|------|----------|------|------|<br>
| 黄山(印象一品) | 条 | 75 | 以下空白 | | |<br>
| 白沙(硬) | 条 | 174 | | | |<br>
| 娇子(蓝时代) | 条 | 63 | | | |<br>
| 黄山(新一品) | 条 | 220 | | | |<br>
| 金圣(庐山) | 条 | 40 | | | |<br>
| 钻石(硬特醇) | 条 | 342 | | | |<br>
| 共计:(品种)6个 | | | 总计:(数量)914条 | | |<br>
| 备注 | | | 卷烟真假待鉴定 | | |
</div>
</div>
<div>渲染结果:
<span class="tooltip-trigger" data-markdown-table="inventory">
<span class="text-blue-500 font-medium border-b border-dotted border-blue-500">库存详情</span>
<div class="tooltip-container tooltip-top tooltip-light tooltip-rich" style="max-width: 500px;">
<div class="tooltip-content">
<div class="tooltip-header">卷烟库存明细表</div>
<div class="tooltip-body">
<!-- Markdown将在这里动态渲染 -->
<div class="markdown-content" id="inventory-table"></div>
</div>
<div class="tooltip-footer">备注:卷烟真假待鉴定</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</span>
</div>
</div>
</div>
<!-- 表格格式悬浮提示 - 深色主题 -->
<div class="preview-block">
<div class="preview-title">表格格式悬浮提示 - 深色主题</div>
<div>配置:<code>tooltipProps: { placement: "top", theme: "dark", rich: true }</code></div>
<div class="mt-2">
<div class="mb-2">
<strong>Markdown源码:</strong>
<div class="bg-gray-100 p-2 rounded text-xs font-mono">
| 品种规格 | 单位 | 数量 | 品种规格 | 单位 | 数量 |<br>
|----------|------|------|----------|------|------|<br>
| 黄山(印象一品) | 条 | 75 | 以下空白 | | |<br>
| 白沙(硬) | 条 | 174 | | | |<br>
| 娇子(蓝时代) | 条 | 63 | | | |<br>
| 黄山(新一品) | 条 | 220 | | | |<br>
| 金圣(庐山) | 条 | 40 | | | |<br>
| 钻石(硬特醇) | 条 | 342 | | | |<br>
| 共计:(品种)6个 | | | 总计:(数量)914条 | | |<br>
| 备注 | | | 卷烟真假待鉴定 | | |
</div>
</div>
<div>渲染结果:
<span class="tooltip-trigger" data-markdown-table="sales">
<span class="text-gray-700 font-medium border-b border-dotted border-gray-700">销售统计</span>
<div class="tooltip-container tooltip-top tooltip-dark tooltip-rich" style="max-width: 500px;">
<div class="tooltip-content">
<div class="tooltip-header">月度销售统计表</div>
<div class="tooltip-body">
<!-- Markdown将在这里动态渲染 -->
<div class="markdown-content" id="sales-table"></div>
</div>
<div class="tooltip-footer">数据更新时间: 2023-10-15 16:30</div>
</div>
<div class="tooltip-arrow"></div>
</div>
</span>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
<script>
// Markdown表格数据
const markdownTables = {
inventory: `| 品种规格 | 单位 | 数量 | 品种规格 | 单位 | 数量 |
|----------|------|------|----------|------|------|
| 黄山(印象一品) | 条 | 75 | 以下空白 | | |
| 白沙(硬) | 条 | 174 | | | |
| 娇子(蓝时代) | 条 | 63 | | | |
| 黄山(新一品) | 条 | 220 | | | |
| 金圣(庐山) | 条 | 40 | | | |
| 钻石(硬特醇) | 条 | 342 | | | |
| 共计:(品种)6个 | | | 总计:(数量)914条 | | |
| 备注 | | | 卷烟真假待鉴定 | | |`,
sales: `| 品种规格 | 单位 | 数量 | 品种规格 | 单位 | 数量 |
|----------|------|------|----------|------|------|
| 黄山(印象一品) | 条 | 75 | 以下空白 | | |
| 白沙(硬) | 条 | 174 | | | |
| 娇子(蓝时代) | 条 | 63 | | | |
| 黄山(新一品) | 条 | 220 | | | |
| 金圣(庐山) | 条 | 40 | | | |
| 钻石(硬特醇) | 条 | 342 | | | |
| 共计:(品种)6个 | | | 总计:(数量)914条 | | |
| 备注 | | | 卷烟真假待鉴定 | | |`
};
// 渲染markdown表格
function renderMarkdownTable(tableKey, targetId) {
const markdownContent = markdownTables[tableKey];
if (markdownContent && typeof marked !== 'undefined') {
const htmlContent = marked.parse(markdownContent);
const targetElement = document.getElementById(targetId);
if (targetElement) {
targetElement.innerHTML = htmlContent;
// 可选:应用通用的表格样式优化
const table = targetElement.querySelector('table');
if (table) {
// 为表格添加通用的样式类
table.classList.add('markdown-rendered-table');
// 可以在这里添加其他通用的表格处理逻辑
// 例如:响应式处理、无障碍属性等
}
}
}
}
// 页面加载完成后渲染表格
document.addEventListener('DOMContentLoaded', function() {
renderMarkdownTable('inventory', 'inventory-table');
renderMarkdownTable('sales', 'sales-table');
});
// 复制按钮功能
document.querySelectorAll('.copy-btn').forEach(btn => {
btn.addEventListener('click', function() {
const codeBlock = this.closest('.code-block').querySelector('pre');
const textArea = document.createElement('textarea');
textArea.value = codeBlock.textContent;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
const originalText = this.textContent;
this.textContent = '已复制';
this.style.backgroundColor = '#22c55e';
this.style.color = 'white';
setTimeout(() => {
this.textContent = originalText;
this.style.backgroundColor = '';
this.style.color = '';
}, 2000);
});
});
// 电话号码复制功能
document.querySelectorAll('.copy-phone-btn').forEach(btn => {
btn.addEventListener('click', function() {
const phoneNumber = this.getAttribute('data-value');
if (!phoneNumber) return;
// 移除任何已存在的提示
const existingTooltip = document.querySelector('.copy-success-tooltip');
if (existingTooltip) {
existingTooltip.remove();
}
// 创建漂浮提示元素
const tooltip = document.createElement('div');
tooltip.className = 'copy-success-tooltip';
tooltip.textContent = '已复制';
this.appendChild(tooltip);
// 使用clipboard API复制文本
navigator.clipboard.writeText(phoneNumber).then(() => {
// 显示提示
setTimeout(() => tooltip.classList.add('show'), 10);
// 改变图标颜色
this.classList.remove('text-gray-400');
this.classList.add('text-green-500');
// 2秒后移除提示
setTimeout(() => {
tooltip.classList.remove('show');
setTimeout(() => {
if (tooltip.parentElement) {
tooltip.parentElement.removeChild(tooltip);
}
}, 300); // 等待淡出动画完成
this.classList.remove('text-green-500');
this.classList.add('text-gray-400');
}, 2000);
}).catch(err => {
console.error('复制失败: ', err);
// 兼容性处理:如果Clipboard API不可用,使用传统方法
const textArea = document.createElement('textarea');
textArea.value = phoneNumber;
textArea.style.position = 'fixed';
textArea.style.left = '-9999px';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
// 显示提示
setTimeout(() => tooltip.classList.add('show'), 10);
// 改变图标颜色
this.classList.remove('text-gray-400');
this.classList.add('text-green-500');
// 2秒后移除提示
setTimeout(() => {
tooltip.classList.remove('show');
setTimeout(() => {
if (tooltip.parentElement) {
tooltip.parentElement.removeChild(tooltip);
}
}, 300);
}, 2000);
} catch (e) {
console.error('复制失败: ', e);
tooltip.textContent = '复制失败';
tooltip.style.backgroundColor = 'rgba(239, 68, 68, 0.9)';
tooltip.classList.add('show');
setTimeout(() => {
tooltip.classList.remove('show');
setTimeout(() => {
if (tooltip.parentElement) {
tooltip.parentElement.removeChild(tooltip);
}
}, 300);
}, 2000);
}
document.body.removeChild(textArea);
});
});
});
// 优化tooltip定位逻辑
function positionTooltips() {
document.querySelectorAll('.tooltip-trigger').forEach(trigger => {
const tooltip = trigger.querySelector('.tooltip-container');
if (!tooltip) return;
const triggerRect = trigger.getBoundingClientRect();
const tooltipRect = tooltip.getBoundingClientRect();
// 获取主题颜色
let themeColor = '#1e293b'; // 默认深色主题颜色
if (tooltip.classList.contains('tooltip-light')) themeColor = '#ffffff';
if (tooltip.classList.contains('tooltip-primary')) themeColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-color');
if (tooltip.classList.contains('tooltip-success')) themeColor = getComputedStyle(document.documentElement).getPropertyValue('--success');
if (tooltip.classList.contains('tooltip-warning')) themeColor = getComputedStyle(document.documentElement).getPropertyValue('--warning');
if (tooltip.classList.contains('tooltip-error')) themeColor = getComputedStyle(document.documentElement).getPropertyValue('--error');
if (tooltip.classList.contains('tooltip-info')) themeColor = getComputedStyle(document.documentElement).getPropertyValue('--info');
// 设置箭头继承主题颜色
const arrow = tooltip.querySelector('.tooltip-arrow');
if (arrow) {
// 直接设置边框颜色而不是使用inherit
if (tooltip.classList.contains('tooltip-light')) {
// 浅色主题使用白色箭头
if (tooltip.classList.contains('tooltip-top')) {
arrow.style.borderColor = '#ffffff transparent transparent transparent';
} else if (tooltip.classList.contains('tooltip-bottom')) {
arrow.style.borderColor = 'transparent transparent #ffffff transparent';
} else if (tooltip.classList.contains('tooltip-left')) {
arrow.style.borderColor = 'transparent transparent transparent #ffffff';
} else if (tooltip.classList.contains('tooltip-right')) {
arrow.style.borderColor = 'transparent #ffffff transparent transparent';
}
} else {
arrow.style.borderColor = 'inherit';
}
}
if (tooltip.classList.contains('tooltip-top') || tooltip.classList.contains('tooltip-bottom')) {
// 水平居中对齐
const left = triggerRect.width / 2 - tooltipRect.width / 2;
tooltip.style.left = `${left}px`;
// 确保箭头居中
if (arrow) {
arrow.style.left = `${tooltipRect.width / 2 - 8}px`;
}
}
if (tooltip.classList.contains('tooltip-left') || tooltip.classList.contains('tooltip-right')) {
// 垂直中心对齐
tooltip.style.top = '50%';
tooltip.style.transform = 'translateY(-50%)';
// 确保箭头垂直居中
if (arrow) {
arrow.style.top = `${tooltipRect.height / 2 - 8}px`;
}
}
});
}
// 初始化tooltip位置
window.addEventListener('DOMContentLoaded', positionTooltips);
// 窗口大小变化时重新定位
window.addEventListener('resize', positionTooltips);
</script>
</body>
</html>