chore: 全量提交(推广页、宣传册、社交资源、视频与后台同步)

Made-with: Cursor
This commit is contained in:
whm
2026-03-20 16:31:12 +08:00
parent 0360ee5261
commit 5067fb6f76
341 changed files with 5283 additions and 108 deletions

View File

@@ -53,7 +53,7 @@
<el-dialog
v-model="dialogVisible"
:title="editId ? '编辑网页' : '新增网页'"
:width="form.content_mode === 'builder' ? '1080px' : '720px'"
:width="form.content_mode === 'builder' || form.content_mode === 'html' ? '1080px' : '720px'"
top="4vh"
@close="resetForm"
>
@@ -63,7 +63,15 @@
:closable="false"
show-icon
style="margin-bottom: 16px"
title="积木模式:从模块左侧 ⋮⋮ 手柄拖拽排序;链接可「选择链接」选站内页或文件。"
title="积木模式:左侧编辑、右侧实时预览;⋮⋮ 拖拽排序;链接可「选择链接」。"
/>
<el-alert
v-if="form.content_mode === 'html'"
type="info"
:closable="false"
show-icon
style="margin-bottom: 16px"
title="HTML 模式:左侧源码、右侧预览(沙箱内不执行脚本,与线上可能略有差异)。"
/>
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-form-item label="Slug" prop="slug">
@@ -91,8 +99,21 @@
<el-form-item label="发布到前台">
<el-switch v-model="form.published" />
</el-form-item>
<el-form-item v-if="form.content_mode === 'html'" label="内容" prop="content">
<el-input v-model="form.content" type="textarea" :rows="14" placeholder="直接编写 HTML" />
<el-form-item v-if="form.content_mode === 'html'" label="内容" prop="content" class="html-form-item">
<div class="html-split">
<div class="html-editor">
<el-input v-model="form.content" type="textarea" :rows="18" placeholder="直接编写 HTML" />
</div>
<div class="html-preview-wrap">
<div class="html-preview-title">实时预览</div>
<iframe
class="html-preview-iframe"
title="html-preview"
sandbox=""
:srcdoc="htmlPreviewSrcdoc"
/>
</div>
</div>
</el-form-item>
<el-form-item v-else label="页面积木" class="builder-form-item page-builder-wrap">
<PageBuilderEditor v-model="form.content" :site-id="siteId" />
@@ -107,7 +128,7 @@
</template>
<script setup>
import { ref, reactive, onMounted, watch } from 'vue'
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getSites } from '../../api/admin'
import { getPages, createPage, updatePage, deletePage } from '../../api/admin'
@@ -215,6 +236,13 @@ const form = reactive({
published: true
})
/** HTML 预览 iframe沙箱禁用脚本避免编辑时执行恶意片段 */
const htmlPreviewSrcdoc = computed(() => {
const raw = form.content || ''
const body = raw.trim() ? raw : '<p style="color:#999">暂无内容</p>'
return `<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style>body{font-family:system-ui,sans-serif;padding:12px;margin:0;background:#fff;color:#222;line-height:1.5;}</style></head><body>${body}</body></html>`
})
function insertBuilderTemplate() {
form.content_mode = 'builder'
if (!form.content?.trim()) {
@@ -314,4 +342,43 @@ onMounted(() => {
.page-builder-wrap {
max-width: 100%;
}
.html-form-item :deep(.el-form-item__content) {
display: block;
margin-left: 0 !important;
}
.html-split {
display: flex;
gap: 16px;
flex-wrap: wrap;
width: 100%;
}
.html-editor {
flex: 1 1 400px;
min-width: 280px;
}
.html-preview-wrap {
flex: 0 1 420px;
width: 100%;
max-width: 480px;
display: flex;
flex-direction: column;
border: 1px solid #dcdfe6;
border-radius: 8px;
overflow: hidden;
background: #fafafa;
}
.html-preview-title {
padding: 8px 12px;
font-size: 13px;
font-weight: 600;
border-bottom: 1px solid #ebeef5;
background: #fff;
}
.html-preview-iframe {
width: 100%;
min-height: 360px;
height: 420px;
border: none;
background: #fff;
}
</style>