优化企业网站功能

This commit is contained in:
2026-08-20 16:21:07 +08:00
parent 112d60b993
commit 3f0fcb88e7
45 changed files with 8758 additions and 5058 deletions
+126 -59
View File
@@ -7,18 +7,34 @@
</el-button>
</div>
<el-alert type="info" :closable="false" style="margin-bottom: 16px">
模板中使用 <b>{yz:标签}</b> 调用数据,循环标签内用 <b>[field:字段/]</b> 输出字段。
本页由引擎注册表自动生成,新增标签后无需改文档。
<el-alert type="info" :closable="false" style="margin-bottom: 12px">
模板中使用 <b>{yz:标签}</b> 调用数据:全局标签直接替换为文本;循环标签成对出现,循环体内用
<b>[field:字段/]</b> 输出字段。本页由引擎注册表自动生成,新增标签后无需改文档。
</el-alert>
<!-- 快捷导航 -->
<div class="quick-nav" v-if="docs.length">
<template v-for="cat in categories" :key="cat.key">
<template v-if="grouped[cat.key]?.length">
<span class="nav-cat">{{ cat.label }}:</span>
<a
v-for="tag in grouped[cat.key]"
:key="cat.key + tag.name"
class="nav-link"
:href="'#tag-' + anchor(tag.name)"
>{{ tag.name }}</a>
</template>
</template>
</div>
<div v-loading="loading">
<template v-for="cat in categories" :key="cat.key">
<div v-if="grouped[cat.key]?.length" class="cat-block">
<h3 class="cat-title">{{ cat.label }}</h3>
<el-card v-for="tag in grouped[cat.key]" :key="tag.name" class="tag-card" shadow="never">
<template #header>
<div class="tag-head">
<div class="tag-head" :id="'tag-' + anchor(tag.name)">
<span class="tag-name">{{ tag.name }}</span>
<code class="tag-syntax">{{ tag.syntax }}</code>
<el-button size="small" text type="primary" @click="copy(tag.syntax)">复制语法</el-button>
@@ -27,36 +43,59 @@
<p class="tag-desc">{{ tag.desc }}</p>
<!-- 参数:表格化 -->
<div v-if="tag.params?.length" class="tag-section">
<div class="sec-label">参数</div>
<ul>
<li v-for="p in tag.params" :key="p"><code>{{ paramName(p) }}</code>{{ paramDesc(p) }}</li>
</ul>
<div class="sec-label">可用参数</div>
<el-table :data="paramRows(tag.params)" size="small" border class="mini-table">
<el-table-column prop="name" label="参数" width="140">
<template #default="{ row }"><code>{{ row.name }}</code></template>
</el-table-column>
<el-table-column prop="desc" label="说明" />
</el-table>
</div>
<div v-if="tag.fields?.length" class="tag-section">
<div class="sec-label">可用字段</div>
<div class="field-tags">
<el-tag
v-for="f in tag.fields"
:key="f"
size="small"
effect="plain"
class="field-tag"
@click="copy('[field:' + fieldName(f) + '/]')"
>
[field:{{ fieldName(f) }}/]
</el-tag>
</div>
<ul class="field-desc">
<li v-for="f in tag.fields" :key="f"><code>[field:{{ fieldName(f) }}/]</code>{{ fieldDesc(f) }}</li>
</ul>
<!-- 全局标签:标签清单表格(标签 / 用法 / 数据来源 / 复制) -->
<div v-else-if="cat.key === 'global' && tag.fields?.length" class="tag-section">
<div class="sec-label">标签清单(点击"复制"后可直接粘贴到模板)</div>
<el-table :data="globalRows(tag.fields)" size="small" border class="mini-table">
<el-table-column prop="name" label="标签" width="220">
<template #default="{ row }">
<code class="gtag">{yz:{{ row.name }}}</code>
</template>
</el-table-column>
<el-table-column prop="desc" label="用法说明" />
<el-table-column prop="source" label="数据来源" width="200" />
<el-table-column label="操作" width="80" align="center">
<template #default="{ row }">
<el-button size="small" text type="primary" @click="copy('{yz:' + row.name + '}')">复制</el-button>
</template>
</el-table-column>
</el-table>
</div>
<!-- 循环/单条标签:字段清单表格(字段 / 说明 / 复制) -->
<div v-else-if="tag.fields?.length" class="tag-section">
<div class="sec-label">循环体内可用字段</div>
<el-table :data="fieldRows(tag.fields)" size="small" border class="mini-table">
<el-table-column prop="name" label="字段" width="220">
<template #default="{ row }">
<code class="gtag">[field:{{ row.name }}/]</code>
</template>
</el-table-column>
<el-table-column prop="desc" label="说明" />
<el-table-column label="操作" width="80" align="center">
<template #default="{ row }">
<el-button size="small" text type="primary" @click="copy('[field:' + row.name + '/]')">复制</el-button>
</template>
</el-table-column>
</el-table>
</div>
<!-- 示例 -->
<div v-if="tag.example" class="tag-section">
<div class="sec-label">
示例
<el-button size="small" text type="primary" @click="copy(tag.example)">复制</el-button>
<el-button size="small" text type="primary" @click="copy(tag.example)">复制示例</el-button>
</div>
<pre class="tag-example">{{ tag.example }}</pre>
</div>
@@ -77,6 +116,7 @@ const docs = ref([])
const loading = ref(false)
const categories = [
{ key: 'guide', label: '入门指南' },
{ key: 'global', label: '全局标签' },
{ key: 'loop', label: '循环标签' },
{ key: 'single', label: '单条内容标签' },
@@ -92,17 +132,35 @@ const grouped = computed(() => {
return out
})
// "row 输出条数,默认 10" -> 名称与说明拆分
const paramName = (p) => (p || '').split(' ')[0]
const paramDesc = (p) => {
const i = (p || '').indexOf(' ')
return i > 0 ? ' — ' + p.slice(i + 1) : ''
}
const fieldName = (f) => (f || '').split(' ')[0]
const fieldDesc = (f) => {
const i = (f || '').indexOf(' ')
return i > 0 ? ' — ' + f.slice(i + 1) : ''
}
const anchor = (name) => encodeURIComponent(name || '')
// "row 输出条数,默认 10" -> { name, desc }
const paramRows = (params) =>
(params || []).map((p) => {
const i = (p || '').indexOf(' ')
return i > 0 ? { name: p.slice(0, i), desc: p.slice(i + 1) } : { name: p, desc: '' }
})
// "sitename 站点名称,常用于… 来源:基本信息-站点名称" -> { name, desc, source }
const globalRows = (fields) =>
(fields || []).map((f) => {
const name = (f || '').split(' ')[0] || ''
let rest = (f || '').slice(name.length).trim()
let source = ''
const si = rest.lastIndexOf(' 来源:')
if (si > 0) {
source = rest.slice(si + 4)
rest = rest.slice(0, si)
}
return { name, desc: rest, source }
})
// "[field:xxx/] 字段" 形式 -> { name, desc }
const fieldRows = (fields) =>
(fields || []).map((f) => {
const i = (f || '').indexOf(' ')
return i > 0 ? { name: f.slice(0, i), desc: f.slice(i + 1) } : { name: f, desc: '' }
})
const copy = async (text) => {
try {
@@ -149,6 +207,28 @@ onMounted(() => {
font-size: 18px;
font-weight: 500;
}
.quick-nav {
background: #fff;
border: 1px solid #ebeef5;
border-radius: 6px;
padding: 10px 14px;
margin-bottom: 16px;
font-size: 13px;
line-height: 2;
}
.nav-cat {
color: #909399;
margin-right: 6px;
}
.nav-link {
display: inline-block;
margin-right: 14px;
color: #1890ff;
text-decoration: none;
}
.nav-link:hover {
text-decoration: underline;
}
.cat-block {
margin-bottom: 24px;
}
@@ -166,6 +246,7 @@ onMounted(() => {
align-items: center;
gap: 12px;
flex-wrap: wrap;
scroll-margin-top: 70px;
}
.tag-name {
font-weight: 600;
@@ -177,14 +258,16 @@ onMounted(() => {
border-radius: 4px;
font-size: 13px;
color: #d63384;
word-break: break-all;
}
.tag-desc {
margin: 0 0 12px;
color: #555;
font-size: 14px;
line-height: 1.8;
}
.tag-section {
margin-top: 10px;
margin-top: 12px;
}
.sec-label {
font-size: 13px;
@@ -195,33 +278,17 @@ onMounted(() => {
align-items: center;
gap: 8px;
}
.tag-section ul {
margin: 0;
padding-left: 20px;
font-size: 13px;
color: #666;
}
.tag-section li {
margin: 3px 0;
}
.field-tags {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin-bottom: 8px;
}
.field-tag {
cursor: pointer;
font-family: Consolas, Monaco, monospace;
}
.field-desc code,
.tag-section code {
.mini-table code {
background: #f5f7fa;
padding: 1px 6px;
border-radius: 3px;
font-size: 12px;
color: #1890ff;
}
.mini-table code.gtag {
color: #d63384;
font-weight: 600;
}
.tag-example {
background: #282c34;
color: #abb2bf;