莫名
This commit is contained in:
@@ -4,11 +4,13 @@
|
||||
</div>
|
||||
<div class="admin-card">
|
||||
<table class="admin-table">
|
||||
<tr><th>封面</th><th>案例标题</th><th>客户</th><th>行业</th><th>日期</th><th>状态</th><th>操作</th></tr>
|
||||
<tr><th>封面</th><th>案例标题</th><th>模式</th><th>客户</th><th>行业</th><th>日期</th><th>状态</th><th>操作</th></tr>
|
||||
<?php foreach ($cases as $c): ?>
|
||||
<?php $cm = empty($c['mode']) ? 'fixed' : $c['mode']; ?>
|
||||
<tr>
|
||||
<td><div class="thum" style="background:<?php echo gradient($c['id']); ?>">🤝</div></td>
|
||||
<td><b><?php echo e($c['title']); ?></b></td>
|
||||
<td><span class="mode-badge <?php echo $cm === 'builder' ? 'builder' : 'fixed'; ?>"><?php echo $cm === 'builder' ? '可视化' : '固定'; ?></span></td>
|
||||
<td class="muted"><?php echo e($c['customer'] ?? ''); ?></td>
|
||||
<td class="muted"><?php echo e($c['industry'] ?? ''); ?></td>
|
||||
<td class="muted"><?php echo e(format_date($c['published_at'])); ?></td>
|
||||
@@ -23,3 +25,8 @@
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</div>
|
||||
<style>
|
||||
.mode-badge{display:inline-block;padding:3px 10px;border-radius:999px;font-size:12px;font-weight:600}
|
||||
.mode-badge.fixed{background:#f1f5f9;color:#475569}
|
||||
.mode-badge.builder{background:#ede9fe;color:#6d28d9}
|
||||
</style>
|
||||
|
||||
+136
-16
@@ -1,14 +1,42 @@
|
||||
<?php
|
||||
/** @var array $c */
|
||||
/** @var string $mode */
|
||||
$v = function ($k, $d = '') use ($c) { return $c ? ($c[$k] ?? $d) : $d; };
|
||||
$isEdit = !empty($c);
|
||||
$mode = $mode ?? 'fixed';
|
||||
$switchUrl = $isEdit ? site_url('admin/cases/switchMode/' . (int)$c['id']) : '';
|
||||
$content = $v('content');
|
||||
$coverVal = $v('cover');
|
||||
?>
|
||||
<div class="page-head">
|
||||
<div><h1><?php echo $isEdit ? '编辑客户案例' : '新增客户案例'; ?></h1></div>
|
||||
<a class="btn-ghost" href="<?php echo site_url('admin/cases'); ?>">← 返回</a>
|
||||
<div>
|
||||
<h1><?php echo $isEdit ? '编辑客户案例' : '新增客户案例'; ?><span class="mode-badge mode-fixed">固定版面</span></h1>
|
||||
<div class="desc">固定版面:填写案例信息 / 封面,详情使用富文本编辑器排版<?php echo $isEdit ? ';可切换为可视化自由排版。' : '。'; ?></div>
|
||||
</div>
|
||||
<?php if ($isEdit): ?>
|
||||
<div class="mode-switch-sel">
|
||||
<label for="modeSel">切换模式</label>
|
||||
<select id="modeSel" class="mode-sel" onchange="location.href='<?php echo $switchUrl; ?>?mode='+this.value">
|
||||
<option value="fixed" <?php echo $mode === 'fixed' ? 'selected' : ''; ?>>固定版面</option>
|
||||
<option value="builder" <?php echo $mode === 'builder' ? 'selected' : ''; ?>>可视化编辑</option>
|
||||
</select>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="mode-switch-sel">
|
||||
<label for="modeSel">排版方式</label>
|
||||
<select id="modeSel" class="mode-sel">
|
||||
<option value="fixed" <?php echo $mode === 'fixed' ? 'selected' : ''; ?>>固定版面</option>
|
||||
<option value="builder" <?php echo $mode === 'builder' ? 'selected' : ''; ?>>可视化编辑</option>
|
||||
</select>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="admin-card">
|
||||
<form id="pbForm" method="post" action="<?php echo site_url($isEdit ? 'admin/cases/update/' . $c['id'] : 'admin/cases/store'); ?>" enctype="multipart/form-data">
|
||||
<form id="fxForm" method="post" action="<?php echo site_url($isEdit ? 'admin/cases/update/' . $c['id'] : 'admin/cases/store'); ?>" enctype="multipart/form-data">
|
||||
<?php echo csrf_field(); ?>
|
||||
<input type="hidden" name="mode" value="fixed">
|
||||
|
||||
<div class="field"><label>案例标题 *</label><input name="title" value="<?php echo e($v('title')); ?>" required></div>
|
||||
<div class="form-grid">
|
||||
<div class="field"><label>客户名称</label><input name="customer" value="<?php echo e($v('customer')); ?>"></div>
|
||||
@@ -20,28 +48,120 @@ $isEdit = !empty($c);
|
||||
</div>
|
||||
<div class="field"><label>摘要</label><input name="summary" value="<?php echo e($v('summary')); ?>"></div>
|
||||
<div class="field"><label>URL 标识(留空按序号生成,短而稳定)</label><input name="slug" value="<?php echo e($v('slug')); ?>" placeholder="留空则自动生成如 12"></div>
|
||||
|
||||
<div class="field">
|
||||
<label>案例详情(可视化编辑)</label>
|
||||
<p class="pb-hint" style="margin:0 0 8px">下方为可视化编辑器:上传素材、拖拽文字/图片/按钮自由排版,拖动右下角缩放、双击文字直接编辑。保存后前台按此布局整页展示。</p>
|
||||
<?php
|
||||
$layoutJson = $v('layout');
|
||||
$layoutArr = $layoutJson ? @json_decode($layoutJson, true) : [];
|
||||
if (!is_array($layoutArr)) $layoutArr = [];
|
||||
echo \Core\View::buffer('admin/parts/builder', ['module' => 'case', 'layout' => $layoutArr]);
|
||||
?>
|
||||
<input type="hidden" name="content" value="<?php echo e($v('content')); ?>">
|
||||
<input type="hidden" name="layout" id="pbLayout">
|
||||
<label>封面图(上传,可选)</label>
|
||||
<input type="file" name="cover" accept="image/*">
|
||||
<?php if ($coverVal): ?>
|
||||
<div class="img-prev"><img src="<?php echo e(site_url($coverVal)); ?>" alt=""><span class="img-prev-path"><?php echo e($coverVal); ?></span></div>
|
||||
<p class="fx-hint">已上传封面;重新选择文件将替换,留空则保留。</p>
|
||||
<?php endif; ?>
|
||||
<input type="text" name="cover_url" value="<?php echo e($coverVal); ?>" placeholder="或填写图片地址 assets/uploads/xxx.jpg 或 http(s)://" style="margin-top:8px">
|
||||
</div>
|
||||
<div class="form-grid">
|
||||
<div class="field"><label>封面图(上传,可选)</label><input type="file" name="cover" accept="image/*"></div>
|
||||
<div class="field"><label>或图片地址</label><input name="cover_url" value="<?php echo e($v('cover')); ?>"></div>
|
||||
|
||||
<div class="field fx-fixed-only">
|
||||
<label>案例详情(富文本编辑器)</label>
|
||||
<div class="fx-toolbar">
|
||||
<button type="button" data-cmd="bold" title="加粗"><b>B</b></button>
|
||||
<button type="button" data-cmd="italic" title="斜体"><i>I</i></button>
|
||||
<button type="button" data-cmd="formatBlock" data-val="H2">H2</button>
|
||||
<button type="button" data-cmd="formatBlock" data-val="H3">H3</button>
|
||||
<button type="button" data-cmd="insertUnorderedList" title="无序列表">• 列表</button>
|
||||
<button type="button" data-cmd="insertOrderedList" title="有序列表">1. 列表</button>
|
||||
<button type="button" data-cmd="formatBlock" data-val="BLOCKQUOTE" title="引用">引用</button>
|
||||
<button type="button" id="fxLink" title="插入链接">链接</button>
|
||||
<button type="button" id="fxImg" title="插入图片">图片</button>
|
||||
</div>
|
||||
<div class="fx-editor" id="fxEditor" contenteditable="true"><?php echo $content; ?></div>
|
||||
<textarea name="content" id="fxContent" hidden><?php echo e($content); ?></textarea>
|
||||
<p class="fx-hint">直接排版正文即可;点击「图片」可从素材库选择或上传新图。保存后前台固定版式展示。</p>
|
||||
</div>
|
||||
|
||||
<div class="field" style="display:flex;align-items:center;gap:8px">
|
||||
<input type="checkbox" name="status" value="1" <?php echo $v('status', 1) ? 'checked' : ''; ?> id="st"> <label for="st" style="margin:0">在前台展示</label>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button class="btn-primary" type="submit">保存</button>
|
||||
<a class="btn-ghost" href="<?php echo site_url('admin/cases'); ?>">取消</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- 图片选择弹层 -->
|
||||
<div class="fx-modal" id="fxModal" hidden>
|
||||
<div class="fx-modal-box">
|
||||
<div class="fx-modal-head"><span>选择图片</span><button type="button" id="fxModalClose">×</button></div>
|
||||
<div class="fx-modal-body">
|
||||
<label class="fx-upload">+ 上传图片<input type="file" id="fxUp" accept="image/*" hidden></label>
|
||||
<div class="fx-lib" id="fxLib"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.mode-switch-sel{display:inline-flex;align-items:center;gap:8px}
|
||||
.mode-switch-sel label{font-size:13px;color:#64748b}
|
||||
.mode-sel{border:1px solid #e2e8f0;border-radius:10px;padding:8px 12px;font-size:14px;background:#fff;color:#334155;cursor:pointer;min-width:140px}
|
||||
.mode-sel:focus{border-color:#0ea5e9;box-shadow:0 0 0 3px rgba(14,165,233,.12)}
|
||||
.mode-badge{display:inline-block;margin-left:10px;padding:2px 10px;border-radius:999px;font-size:12px;font-weight:600;vertical-align:middle;line-height:1.7}
|
||||
.mode-badge.mode-fixed{background:#e0f2fe;color:#0369a1}
|
||||
.mode-badge.mode-builder{background:#ede9fe;color:#6d28d9}
|
||||
.img-prev{display:flex;align-items:center;gap:10px;margin-top:10px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:8px 10px}
|
||||
.img-prev img{width:72px;height:54px;object-fit:cover;border-radius:8px;display:block}
|
||||
.img-prev-path{font-size:12px;color:#94a3b8;word-break:break-all}
|
||||
.fx-toolbar{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}
|
||||
.fx-toolbar button{width:auto;min-width:38px;height:34px;padding:0 10px;border:1px solid #e2e8f0;background:#fff;border-radius:8px;cursor:pointer;font-size:14px;color:#334155}
|
||||
.fx-toolbar button:hover{border-color:#0ea5e9;color:#0ea5e9}
|
||||
.fx-editor{min-height:320px;border:1px solid #e2e8f0;border-radius:10px;padding:16px 18px;font-size:16px;line-height:1.9;outline:none;background:#fff;overflow:auto}
|
||||
.fx-editor:focus{border-color:#0ea5e9;box-shadow:0 0 0 3px rgba(14,165,233,.12)}
|
||||
.fx-editor h2{font-size:24px;margin:.6em 0 .4em}
|
||||
.fx-editor h3{font-size:20px;margin:.6em 0 .4em}
|
||||
.fx-editor blockquote{margin:.6em 0;padding:8px 14px;border-left:4px solid #0ea5e9;color:#475569;background:#f8fafc}
|
||||
.fx-editor img{max-width:100%;height:auto;border-radius:8px;display:block;margin:8px 0}
|
||||
.fx-editor a{color:#0ea5e9}
|
||||
.fx-hint{font-size:12px;color:#94a3b8;margin:8px 2px 0}
|
||||
.fx-modal{position:fixed;inset:0;background:rgba(15,23,42,.45);display:flex;align-items:center;justify-content:center;z-index:80}
|
||||
.fx-modal[hidden]{display:none}
|
||||
.fx-modal-box{background:#fff;border-radius:14px;width:420px;max-width:92vw;overflow:hidden}
|
||||
.fx-modal-head{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid #e2e8f0;font-weight:700}
|
||||
.fx-modal-head button{border:none;background:none;font-size:22px;cursor:pointer;color:#64748b;line-height:1}
|
||||
.fx-modal-body{padding:16px;max-height:60vh;overflow:auto}
|
||||
.fx-upload{display:block;text-align:center;background:#0ea5e9;color:#fff;border-radius:10px;padding:10px;cursor:pointer;font-weight:600;margin-bottom:12px}
|
||||
.fx-lib{display:flex;flex-wrap:wrap;gap:8px}
|
||||
.fx-lib img{width:72px;height:72px;object-fit:cover;border-radius:8px;cursor:pointer;border:2px solid transparent}
|
||||
.fx-lib img:hover{border-color:#0ea5e9}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
window.__PB_MEDIA__ = '<?php echo site_url('admin/media'); ?>';
|
||||
window.__PB_UPLOAD__ = '<?php echo site_url('admin/media/upload'); ?>';
|
||||
window.__PB_CSRF__ = '<?php echo csrf_token(); ?>';
|
||||
</script>
|
||||
<script src="<?php echo asset('js/fixed-editor.js'); ?>"></script>
|
||||
<script>
|
||||
// 新增案例时按「排版方式」选择器联动:选可视化编辑则隐藏正文编辑器,并提示保存后进入可视化编辑器
|
||||
(function(){
|
||||
var sel = document.getElementById('modeSel');
|
||||
if(!sel) return;
|
||||
var isCreate = <?php echo $isEdit ? 'false' : 'true'; ?>;
|
||||
var modeField = document.querySelector('#fxForm input[name="mode"]');
|
||||
var fixedOnly = document.querySelectorAll('.fx-fixed-only');
|
||||
var note = document.createElement('p');
|
||||
note.className = 'fx-hint fx-builder-note';
|
||||
note.style.cssText = 'margin-top:10px;color:#6d28d9;background:#f5f3ff;border:1px solid #ddd6fe;border-radius:8px;padding:8px 12px;display:none';
|
||||
note.textContent = '已选择「可视化编辑」:案例详情无需填写,保存后将进入可视化编辑器排版。';
|
||||
var firstFixed = fixedOnly[0];
|
||||
if(firstFixed && firstFixed.parentNode){ firstFixed.parentNode.insertBefore(note, firstFixed); }
|
||||
function apply(){
|
||||
var m = sel.value;
|
||||
if(modeField) modeField.value = m;
|
||||
if(!isCreate) return;
|
||||
var isBuilder = (m === 'builder');
|
||||
for(var i=0;i<fixedOnly.length;i++){ fixedOnly[i].style.display = isBuilder ? 'none' : ''; }
|
||||
note.style.display = isBuilder ? 'block' : 'none';
|
||||
}
|
||||
sel.addEventListener('change', apply);
|
||||
apply();
|
||||
})();
|
||||
</script>
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
</div>
|
||||
<div class="admin-card">
|
||||
<table class="admin-table">
|
||||
<tr><th>图标</th><th>名称</th><th>标识</th><th>描述</th><th>操作</th></tr>
|
||||
<tr><th>图标</th><th>名称</th><th>标识</th><th>模式</th><th>描述</th><th>操作</th></tr>
|
||||
<?php foreach ($cats as $c): ?>
|
||||
<?php $cm = empty($c['mode']) ? 'fixed' : $c['mode']; ?>
|
||||
<tr>
|
||||
<td style="font-size:24px"><?php echo e($c['icon']); ?></td>
|
||||
<td><b><?php echo e($c['name']); ?></b></td>
|
||||
<td class="muted"><?php echo e($c['slug']); ?></td>
|
||||
<td><span class="mode-badge <?php echo $cm === 'builder' ? 'builder' : 'fixed'; ?>"><?php echo $cm === 'builder' ? '可视化' : '固定'; ?></span></td>
|
||||
<td class="muted"><?php echo e(mb_substr($c['description'] ?? '', 0, 24)); ?></td>
|
||||
<td>
|
||||
<div class="row-actions">
|
||||
@@ -21,3 +23,8 @@
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</div>
|
||||
<style>
|
||||
.mode-badge{display:inline-block;padding:3px 10px;border-radius:999px;font-size:12px;font-weight:600}
|
||||
.mode-badge.fixed{background:#f1f5f9;color:#475569}
|
||||
.mode-badge.builder{background:#ede9fe;color:#6d28d9}
|
||||
</style>
|
||||
|
||||
@@ -1,37 +1,101 @@
|
||||
<?php
|
||||
/** @var array $c */
|
||||
/** @var string $mode */
|
||||
$v = function ($k, $d = '') use ($c) { return $c ? ($c[$k] ?? $d) : $d; };
|
||||
$isEdit = !empty($c);
|
||||
$mode = $mode ?? 'fixed';
|
||||
$switchUrl = $isEdit ? site_url('admin/categories/switchMode/' . (int)$c['id']) : '';
|
||||
$desc = $v('description');
|
||||
?>
|
||||
<div class="page-head">
|
||||
<div><h1><?php echo $isEdit ? '编辑分类' : '新增分类'; ?></h1></div>
|
||||
<a class="btn-ghost" href="<?php echo site_url('admin/categories'); ?>">← 返回</a>
|
||||
<div>
|
||||
<h1><?php echo $isEdit ? '编辑分类' : '新增分类'; ?><span class="mode-badge mode-fixed">固定版面</span></h1>
|
||||
<div class="desc">固定版面:填写分类名称 / 图标 / 描述等基本信息<?php echo $isEdit ? ';可切换为可视化自由排版。' : '。'; ?></div>
|
||||
</div>
|
||||
<?php if ($isEdit): ?>
|
||||
<div class="mode-switch-sel">
|
||||
<label for="modeSel">切换模式</label>
|
||||
<select id="modeSel" class="mode-sel" onchange="location.href='<?php echo $switchUrl; ?>?mode='+this.value">
|
||||
<option value="fixed" <?php echo $mode === 'fixed' ? 'selected' : ''; ?>>固定版面</option>
|
||||
<option value="builder" <?php echo $mode === 'builder' ? 'selected' : ''; ?>>可视化编辑</option>
|
||||
</select>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="mode-switch-sel">
|
||||
<label for="modeSel">排版方式</label>
|
||||
<select id="modeSel" class="mode-sel">
|
||||
<option value="fixed" <?php echo $mode === 'fixed' ? 'selected' : ''; ?>>固定版面</option>
|
||||
<option value="builder" <?php echo $mode === 'builder' ? 'selected' : ''; ?>>可视化编辑</option>
|
||||
</select>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="admin-card">
|
||||
<form id="pbForm" method="post" action="<?php echo site_url($isEdit ? 'admin/categories/update/' . $c['id'] : 'admin/categories/store'); ?>">
|
||||
<form id="fxForm" method="post" action="<?php echo site_url($isEdit ? 'admin/categories/update/' . $c['id'] : 'admin/categories/store'); ?>">
|
||||
<?php echo csrf_field(); ?>
|
||||
<input type="hidden" name="mode" value="fixed">
|
||||
|
||||
<div class="form-grid">
|
||||
<div class="field"><label>分类名称 *</label><input name="name" value="<?php echo e($v('name')); ?>" required></div>
|
||||
<div class="field"><label>图标(emoji)</label><input name="icon" value="<?php echo e($v('icon', '❄')); ?>"></div>
|
||||
</div>
|
||||
<div class="form-grid">
|
||||
<div class="field"><label>标识(留空按序号生成)</label><input name="slug" value="<?php echo e($v('slug')); ?>"></div>
|
||||
<div class="field"><label>排序</label><input name="sort_order" type="number" value="<?php echo e($v('sort_order', 0)); ?>"></div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>描述(可视化编辑)</label>
|
||||
<p class="pb-hint" style="margin:0 0 8px">下方为可视化编辑器:上传素材、拖拽文字/图片/按钮自由排版。当前分类无独立前台详情页,编辑保存后可用于后续扩展或作为内容版式储备。</p>
|
||||
<?php
|
||||
$layoutJson = $v('layout');
|
||||
$layoutArr = $layoutJson ? @json_decode($layoutJson, true) : [];
|
||||
if (!is_array($layoutArr)) $layoutArr = [];
|
||||
echo \Core\View::buffer('admin/parts/builder', ['module' => 'category', 'layout' => $layoutArr]);
|
||||
?>
|
||||
<input type="hidden" name="layout" id="pbLayout">
|
||||
|
||||
<div class="field fx-fixed-only">
|
||||
<label>分类描述</label>
|
||||
<textarea name="description" rows="4" placeholder="分类简介,用于前台分类展示区域"><?php echo e($desc); ?></textarea>
|
||||
<p class="fx-hint">纯文本描述,保存后前台分类列表展示。如需复杂排版可切换为可视化编辑。</p>
|
||||
</div>
|
||||
|
||||
<div class="field" style="display:flex;align-items:center;gap:8px">
|
||||
<input type="checkbox" name="status" value="1" <?php echo $v('status', 1) ? 'checked' : ''; ?> id="st"> <label for="st" style="margin:0">显示</label>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button class="btn-primary" type="submit">保存</button>
|
||||
<a class="btn-ghost" href="<?php echo site_url('admin/categories'); ?>">取消</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.mode-switch-sel{display:inline-flex;align-items:center;gap:8px}
|
||||
.mode-switch-sel label{font-size:13px;color:#64748b}
|
||||
.mode-sel{border:1px solid #e2e8f0;border-radius:10px;padding:8px 12px;font-size:14px;background:#fff;color:#334155;cursor:pointer;min-width:140px}
|
||||
.mode-sel:focus{border-color:#0ea5e9;box-shadow:0 0 0 3px rgba(14,165,233,.12)}
|
||||
.mode-badge{display:inline-block;margin-left:10px;padding:2px 10px;border-radius:999px;font-size:12px;font-weight:600;vertical-align:middle;line-height:1.7}
|
||||
.mode-badge.mode-fixed{background:#e0f2fe;color:#0369a1}
|
||||
.mode-badge.mode-builder{background:#ede9fe;color:#6d28d9}
|
||||
.fx-hint{font-size:12px;color:#94a3b8;margin:8px 2px 0}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// 新增分类时按「排版方式」选择器联动:选可视化编辑则隐藏描述,并提示保存后进入可视化编辑器
|
||||
(function(){
|
||||
var sel = document.getElementById('modeSel');
|
||||
if(!sel) return;
|
||||
var isCreate = <?php echo $isEdit ? 'false' : 'true'; ?>;
|
||||
var modeField = document.querySelector('#fxForm input[name="mode"]');
|
||||
var fixedOnly = document.querySelectorAll('.fx-fixed-only');
|
||||
var note = document.createElement('p');
|
||||
note.className = 'fx-hint fx-builder-note';
|
||||
note.style.cssText = 'margin-top:10px;color:#6d28d9;background:#f5f3ff;border:1px solid #ddd6fe;border-radius:8px;padding:8px 12px;display:none';
|
||||
note.textContent = '已选择「可视化编辑」:描述无需填写,保存后将进入可视化编辑器排版分类内容。';
|
||||
var firstFixed = fixedOnly[0];
|
||||
if(firstFixed && firstFixed.parentNode){ firstFixed.parentNode.insertBefore(note, firstFixed); }
|
||||
function apply(){
|
||||
var m = sel.value;
|
||||
if(modeField) modeField.value = m;
|
||||
if(!isCreate) return;
|
||||
var isBuilder = (m === 'builder');
|
||||
for(var i=0;i<fixedOnly.length;i++){ fixedOnly[i].style.display = isBuilder ? 'none' : ''; }
|
||||
note.style.display = isBuilder ? 'block' : 'none';
|
||||
}
|
||||
sel.addEventListener('change', apply);
|
||||
apply();
|
||||
})();
|
||||
</script>
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
</div>
|
||||
<div class="admin-card">
|
||||
<table class="admin-table">
|
||||
<tr><th>封面</th><th>标题</th><th>作者</th><th>日期</th><th>状态</th><th>操作</th></tr>
|
||||
<tr><th>封面</th><th>标题</th><th>模式</th><th>作者</th><th>日期</th><th>状态</th><th>操作</th></tr>
|
||||
<?php foreach ($news as $n): ?>
|
||||
<?php $nm = empty($n['mode']) ? 'fixed' : $n['mode']; ?>
|
||||
<tr>
|
||||
<td><div class="thum" style="background:<?php echo gradient($n['id']); ?>">📰</div></td>
|
||||
<td><b><?php echo e($n['title']); ?></b></td>
|
||||
<td><span class="mode-badge <?php echo $nm === 'builder' ? 'builder' : 'fixed'; ?>"><?php echo $nm === 'builder' ? '可视化' : '固定'; ?></span></td>
|
||||
<td class="muted"><?php echo e($n['author']); ?></td>
|
||||
<td class="muted"><?php echo e(format_date($n['published_at'])); ?></td>
|
||||
<td><?php echo ($n['status'] ?? 1) ? '<span class="tag-mini">已发布</span>' : '<span class="muted">草稿</span>'; ?></td>
|
||||
@@ -22,3 +24,8 @@
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</div>
|
||||
<style>
|
||||
.mode-badge{display:inline-block;padding:3px 10px;border-radius:999px;font-size:12px;font-weight:600}
|
||||
.mode-badge.fixed{background:#f1f5f9;color:#475569}
|
||||
.mode-badge.builder{background:#ede9fe;color:#6d28d9}
|
||||
</style>
|
||||
|
||||
+136
-16
@@ -1,14 +1,42 @@
|
||||
<?php
|
||||
/** @var array $n */
|
||||
/** @var string $mode */
|
||||
$v = function ($k, $d = '') use ($n) { return $n ? ($n[$k] ?? $d) : $d; };
|
||||
$isEdit = !empty($n);
|
||||
$mode = $mode ?? 'fixed';
|
||||
$switchUrl = $isEdit ? site_url('admin/news/switchMode/' . (int)$n['id']) : '';
|
||||
$content = $v('content');
|
||||
$coverVal = $v('cover');
|
||||
?>
|
||||
<div class="page-head">
|
||||
<div><h1><?php echo $isEdit ? '编辑新闻' : '写新闻'; ?></h1></div>
|
||||
<a class="btn-ghost" href="<?php echo site_url('admin/news'); ?>">← 返回</a>
|
||||
<div>
|
||||
<h1><?php echo $isEdit ? '编辑新闻' : '写新闻'; ?><span class="mode-badge mode-fixed">固定版面</span></h1>
|
||||
<div class="desc">固定版面:填写标题 / 摘要 / 封面,正文使用富文本编辑器排版<?php echo $isEdit ? ';可切换为可视化自由排版。' : '。'; ?></div>
|
||||
</div>
|
||||
<?php if ($isEdit): ?>
|
||||
<div class="mode-switch-sel">
|
||||
<label for="modeSel">切换模式</label>
|
||||
<select id="modeSel" class="mode-sel" onchange="location.href='<?php echo $switchUrl; ?>?mode='+this.value">
|
||||
<option value="fixed" <?php echo $mode === 'fixed' ? 'selected' : ''; ?>>固定版面</option>
|
||||
<option value="builder" <?php echo $mode === 'builder' ? 'selected' : ''; ?>>可视化编辑</option>
|
||||
</select>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="mode-switch-sel">
|
||||
<label for="modeSel">排版方式</label>
|
||||
<select id="modeSel" class="mode-sel">
|
||||
<option value="fixed" <?php echo $mode === 'fixed' ? 'selected' : ''; ?>>固定版面</option>
|
||||
<option value="builder" <?php echo $mode === 'builder' ? 'selected' : ''; ?>>可视化编辑</option>
|
||||
</select>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="admin-card">
|
||||
<form id="pbForm" method="post" action="<?php echo site_url($isEdit ? 'admin/news/update/' . $n['id'] : 'admin/news/store'); ?>" enctype="multipart/form-data">
|
||||
<form id="fxForm" method="post" action="<?php echo site_url($isEdit ? 'admin/news/update/' . $n['id'] : 'admin/news/store'); ?>" enctype="multipart/form-data">
|
||||
<?php echo csrf_field(); ?>
|
||||
<input type="hidden" name="mode" value="fixed">
|
||||
|
||||
<div class="field"><label>标题 *</label><input name="title" value="<?php echo e($v('title')); ?>" required></div>
|
||||
<div class="form-grid">
|
||||
<div class="field"><label>作者</label><input name="author" value="<?php echo e($v('author', '酷冰甲')); ?>"></div>
|
||||
@@ -16,28 +44,120 @@ $isEdit = !empty($n);
|
||||
</div>
|
||||
<div class="field"><label>摘要</label><input name="summary" value="<?php echo e($v('summary')); ?>"></div>
|
||||
<div class="field"><label>URL 标识(留空按序号生成,短而稳定)</label><input name="slug" value="<?php echo e($v('slug')); ?>" placeholder="留空则自动生成如 12"></div>
|
||||
|
||||
<div class="field">
|
||||
<label>正文(可视化编辑)</label>
|
||||
<p class="pb-hint" style="margin:0 0 8px">下方为可视化编辑器:上传素材、拖拽文字/图片/按钮自由排版,拖动右下角缩放、双击文字直接编辑。保存后前台按此布局整页展示。</p>
|
||||
<?php
|
||||
$layoutJson = $v('layout');
|
||||
$layoutArr = $layoutJson ? @json_decode($layoutJson, true) : [];
|
||||
if (!is_array($layoutArr)) $layoutArr = [];
|
||||
echo \Core\View::buffer('admin/parts/builder', ['module' => 'news', 'layout' => $layoutArr]);
|
||||
?>
|
||||
<input type="hidden" name="content" value="<?php echo e($v('content')); ?>">
|
||||
<input type="hidden" name="layout" id="pbLayout">
|
||||
<label>封面图(上传,可选)</label>
|
||||
<input type="file" name="cover" accept="image/*">
|
||||
<?php if ($coverVal): ?>
|
||||
<div class="img-prev"><img src="<?php echo e(site_url($coverVal)); ?>" alt=""><span class="img-prev-path"><?php echo e($coverVal); ?></span></div>
|
||||
<p class="fx-hint">已上传封面;重新选择文件将替换,留空则保留。</p>
|
||||
<?php endif; ?>
|
||||
<input type="text" name="cover_url" value="<?php echo e($coverVal); ?>" placeholder="或填写图片地址 assets/uploads/xxx.jpg 或 http(s)://" style="margin-top:8px">
|
||||
</div>
|
||||
<div class="form-grid">
|
||||
<div class="field"><label>封面图(上传,可选)</label><input type="file" name="cover" accept="image/*"></div>
|
||||
<div class="field"><label>或图片地址</label><input name="cover_url" value="<?php echo e($v('cover')); ?>"></div>
|
||||
|
||||
<div class="field fx-fixed-only">
|
||||
<label>正文内容(富文本编辑器)</label>
|
||||
<div class="fx-toolbar">
|
||||
<button type="button" data-cmd="bold" title="加粗"><b>B</b></button>
|
||||
<button type="button" data-cmd="italic" title="斜体"><i>I</i></button>
|
||||
<button type="button" data-cmd="formatBlock" data-val="H2">H2</button>
|
||||
<button type="button" data-cmd="formatBlock" data-val="H3">H3</button>
|
||||
<button type="button" data-cmd="insertUnorderedList" title="无序列表">• 列表</button>
|
||||
<button type="button" data-cmd="insertOrderedList" title="有序列表">1. 列表</button>
|
||||
<button type="button" data-cmd="formatBlock" data-val="BLOCKQUOTE" title="引用">引用</button>
|
||||
<button type="button" id="fxLink" title="插入链接">链接</button>
|
||||
<button type="button" id="fxImg" title="插入图片">图片</button>
|
||||
</div>
|
||||
<div class="fx-editor" id="fxEditor" contenteditable="true"><?php echo $content; ?></div>
|
||||
<textarea name="content" id="fxContent" hidden><?php echo e($content); ?></textarea>
|
||||
<p class="fx-hint">直接排版正文即可;点击「图片」可从素材库选择或上传新图。保存后前台固定版式展示。</p>
|
||||
</div>
|
||||
|
||||
<div class="field" style="display:flex;align-items:center;gap:8px">
|
||||
<input type="checkbox" name="status" value="1" <?php echo $v('status', 1) ? 'checked' : ''; ?> id="st"> <label for="st" style="margin:0">立即发布</label>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button class="btn-primary" type="submit">保存</button>
|
||||
<a class="btn-ghost" href="<?php echo site_url('admin/news'); ?>">取消</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- 图片选择弹层 -->
|
||||
<div class="fx-modal" id="fxModal" hidden>
|
||||
<div class="fx-modal-box">
|
||||
<div class="fx-modal-head"><span>选择图片</span><button type="button" id="fxModalClose">×</button></div>
|
||||
<div class="fx-modal-body">
|
||||
<label class="fx-upload">+ 上传图片<input type="file" id="fxUp" accept="image/*" hidden></label>
|
||||
<div class="fx-lib" id="fxLib"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.mode-switch-sel{display:inline-flex;align-items:center;gap:8px}
|
||||
.mode-switch-sel label{font-size:13px;color:#64748b}
|
||||
.mode-sel{border:1px solid #e2e8f0;border-radius:10px;padding:8px 12px;font-size:14px;background:#fff;color:#334155;cursor:pointer;min-width:140px}
|
||||
.mode-sel:focus{border-color:#0ea5e9;box-shadow:0 0 0 3px rgba(14,165,233,.12)}
|
||||
.mode-badge{display:inline-block;margin-left:10px;padding:2px 10px;border-radius:999px;font-size:12px;font-weight:600;vertical-align:middle;line-height:1.7}
|
||||
.mode-badge.mode-fixed{background:#e0f2fe;color:#0369a1}
|
||||
.mode-badge.mode-builder{background:#ede9fe;color:#6d28d9}
|
||||
.img-prev{display:flex;align-items:center;gap:10px;margin-top:10px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:8px 10px}
|
||||
.img-prev img{width:72px;height:54px;object-fit:cover;border-radius:8px;display:block}
|
||||
.img-prev-path{font-size:12px;color:#94a3b8;word-break:break-all}
|
||||
.fx-toolbar{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}
|
||||
.fx-toolbar button{width:auto;min-width:38px;height:34px;padding:0 10px;border:1px solid #e2e8f0;background:#fff;border-radius:8px;cursor:pointer;font-size:14px;color:#334155}
|
||||
.fx-toolbar button:hover{border-color:#0ea5e9;color:#0ea5e9}
|
||||
.fx-editor{min-height:320px;border:1px solid #e2e8f0;border-radius:10px;padding:16px 18px;font-size:16px;line-height:1.9;outline:none;background:#fff;overflow:auto}
|
||||
.fx-editor:focus{border-color:#0ea5e9;box-shadow:0 0 0 3px rgba(14,165,233,.12)}
|
||||
.fx-editor h2{font-size:24px;margin:.6em 0 .4em}
|
||||
.fx-editor h3{font-size:20px;margin:.6em 0 .4em}
|
||||
.fx-editor blockquote{margin:.6em 0;padding:8px 14px;border-left:4px solid #0ea5e9;color:#475569;background:#f8fafc}
|
||||
.fx-editor img{max-width:100%;height:auto;border-radius:8px;display:block;margin:8px 0}
|
||||
.fx-editor a{color:#0ea5e9}
|
||||
.fx-hint{font-size:12px;color:#94a3b8;margin:8px 2px 0}
|
||||
.fx-modal{position:fixed;inset:0;background:rgba(15,23,42,.45);display:flex;align-items:center;justify-content:center;z-index:80}
|
||||
.fx-modal[hidden]{display:none}
|
||||
.fx-modal-box{background:#fff;border-radius:14px;width:420px;max-width:92vw;overflow:hidden}
|
||||
.fx-modal-head{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid #e2e8f0;font-weight:700}
|
||||
.fx-modal-head button{border:none;background:none;font-size:22px;cursor:pointer;color:#64748b;line-height:1}
|
||||
.fx-modal-body{padding:16px;max-height:60vh;overflow:auto}
|
||||
.fx-upload{display:block;text-align:center;background:#0ea5e9;color:#fff;border-radius:10px;padding:10px;cursor:pointer;font-weight:600;margin-bottom:12px}
|
||||
.fx-lib{display:flex;flex-wrap:wrap;gap:8px}
|
||||
.fx-lib img{width:72px;height:72px;object-fit:cover;border-radius:8px;cursor:pointer;border:2px solid transparent}
|
||||
.fx-lib img:hover{border-color:#0ea5e9}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
window.__PB_MEDIA__ = '<?php echo site_url('admin/media'); ?>';
|
||||
window.__PB_UPLOAD__ = '<?php echo site_url('admin/media/upload'); ?>';
|
||||
window.__PB_CSRF__ = '<?php echo csrf_token(); ?>';
|
||||
</script>
|
||||
<script src="<?php echo asset('js/fixed-editor.js'); ?>"></script>
|
||||
<script>
|
||||
// 新增新闻时按「排版方式」选择器联动:选可视化编辑则隐藏正文编辑器,并提示保存后进入可视化编辑器
|
||||
(function(){
|
||||
var sel = document.getElementById('modeSel');
|
||||
if(!sel) return;
|
||||
var isCreate = <?php echo $isEdit ? 'false' : 'true'; ?>;
|
||||
var modeField = document.querySelector('#fxForm input[name="mode"]');
|
||||
var fixedOnly = document.querySelectorAll('.fx-fixed-only');
|
||||
var note = document.createElement('p');
|
||||
note.className = 'fx-hint fx-builder-note';
|
||||
note.style.cssText = 'margin-top:10px;color:#6d28d9;background:#f5f3ff;border:1px solid #ddd6fe;border-radius:8px;padding:8px 12px;display:none';
|
||||
note.textContent = '已选择「可视化编辑」:正文无需填写,保存后将进入可视化编辑器排版新闻详情。';
|
||||
var firstFixed = fixedOnly[0];
|
||||
if(firstFixed && firstFixed.parentNode){ firstFixed.parentNode.insertBefore(note, firstFixed); }
|
||||
function apply(){
|
||||
var m = sel.value;
|
||||
if(modeField) modeField.value = m;
|
||||
if(!isCreate) return;
|
||||
var isBuilder = (m === 'builder');
|
||||
for(var i=0;i<fixedOnly.length;i++){ fixedOnly[i].style.display = isBuilder ? 'none' : ''; }
|
||||
note.style.display = isBuilder ? 'block' : 'none';
|
||||
}
|
||||
sel.addEventListener('change', apply);
|
||||
apply();
|
||||
})();
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<?php
|
||||
/** @var array $p */
|
||||
/** @var array $layout */
|
||||
/** @var string $mode */
|
||||
$v = function ($k, $d = '') use ($p) { return $p ? ($p[$k] ?? $d) : $d; };
|
||||
$isEdit = !empty($p);
|
||||
$switchUrl = $isEdit ? site_url('admin/pages/switchMode/' . (int)$p['id']) : '';
|
||||
$initial = json_encode($layout ?: []);
|
||||
?>
|
||||
<div class="pb-root">
|
||||
@@ -8,6 +12,16 @@ $initial = json_encode($layout ?: []);
|
||||
<div class="pb-top-left">
|
||||
<a class="btn-ghost" href="<?php echo site_url('admin/pages'); ?>">← 返回</a>
|
||||
<span class="pb-t">可视化编辑:<?php echo e($p['title']); ?></span>
|
||||
<span class="mode-badge mode-builder">可视化编辑</span>
|
||||
<?php if ($isEdit): ?>
|
||||
<div class="mode-switch-sel">
|
||||
<label for="modeSel">切换模式</label>
|
||||
<select id="modeSel" class="mode-sel" onchange="location.href='<?php echo $switchUrl; ?>?mode='+this.value">
|
||||
<option value="fixed" <?php echo $mode === 'fixed' ? 'selected' : ''; ?>>固定版面</option>
|
||||
<option value="builder" <?php echo $mode === 'builder' ? 'selected' : ''; ?>>可视化编辑</option>
|
||||
</select>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<form id="pbForm" method="post" action="<?php echo site_url('admin/pages/update/' . $p['id']); ?>" class="pb-top-form">
|
||||
<?php echo csrf_field(); ?>
|
||||
@@ -55,6 +69,13 @@ $initial = json_encode($layout ?: []);
|
||||
.pb-topbar{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:14px 18px;background:#fff;border-bottom:1px solid var(--admin-border,#e2e8f0);position:sticky;top:0;z-index:30}
|
||||
.pb-top-left{display:flex;align-items:center;gap:12px}
|
||||
.pb-t{font-weight:700;color:#0f172a}
|
||||
.mode-switch-sel{display:inline-flex;align-items:center;gap:8px}
|
||||
.mode-switch-sel label{font-size:13px;color:#64748b}
|
||||
.mode-sel{border:1px solid #e2e8f0;border-radius:10px;padding:6px 12px;font-size:13px;background:#fff;color:#334155;cursor:pointer;min-width:140px}
|
||||
.mode-sel:focus{border-color:#0ea5e9;box-shadow:0 0 0 3px rgba(14,165,233,.12)}
|
||||
.mode-badge{display:inline-block;margin-left:6px;padding:2px 10px;border-radius:999px;font-size:12px;font-weight:600;vertical-align:middle;line-height:1.7}
|
||||
.mode-badge.mode-fixed{background:#e0f2fe;color:#0369a1}
|
||||
.mode-badge.mode-builder{background:#ede9fe;color:#6d28d9}
|
||||
.pb-top-form{display:flex;align-items:center;gap:10px}
|
||||
.pb-title{border:1px solid #e2e8f0;border-radius:10px;padding:8px 12px;font-size:14px;min-width:200px}
|
||||
.pb-workspace{display:flex;gap:0;min-height:72vh}
|
||||
@@ -93,5 +114,7 @@ window.__PB_INIT__ = <?php echo $initial; ?>;
|
||||
window.__PB_MEDIA__ = '<?php echo site_url('admin/media'); ?>';
|
||||
window.__PB_UPLOAD__ = '<?php echo site_url('admin/media/upload'); ?>';
|
||||
window.__PB_CSRF__ = '<?php echo csrf_token(); ?>';
|
||||
window.__PB_MODULE__ = 'page';
|
||||
window.__PB_DELETE__ = '<?php echo site_url('admin/media/delete/'); ?>';
|
||||
</script>
|
||||
<script src="<?php echo asset('js/page-builder.js'); ?>"></script>
|
||||
|
||||
@@ -1,15 +1,103 @@
|
||||
<?php
|
||||
/** @var array $p */
|
||||
/** @var string $mode */
|
||||
$v = function ($k, $d = '') use ($p) { return $p ? ($p[$k] ?? $d) : $d; };
|
||||
$isEdit = !empty($p);
|
||||
$mode = $mode ?? 'fixed';
|
||||
$switchUrl = $isEdit ? site_url('admin/pages/switchMode/' . (int)$p['id']) : '';
|
||||
?>
|
||||
<div class="page-head">
|
||||
<div><h1>编辑单页:<?php echo e($p['title']); ?></h1><div class="desc">支持 HTML 标签</div></div>
|
||||
<a class="btn-ghost" href="<?php echo site_url('admin/pages'); ?>">← 返回</a>
|
||||
<div>
|
||||
<h1>编辑单页:<?php echo e($p['title']); ?><span class="mode-badge mode-fixed">固定版面</span></h1>
|
||||
<div class="desc">固定版面:页面套用统一模板(标题区 + 正文 + 联系按钮),您只需编辑正文内容。</div>
|
||||
</div>
|
||||
<?php if ($isEdit): ?>
|
||||
<div class="mode-switch-sel">
|
||||
<label for="modeSel">切换模式</label>
|
||||
<select id="modeSel" class="mode-sel" onchange="location.href='<?php echo $switchUrl; ?>?mode='+this.value">
|
||||
<option value="fixed" <?php echo $mode === 'fixed' ? 'selected' : ''; ?>>固定版面</option>
|
||||
<option value="builder" <?php echo $mode === 'builder' ? 'selected' : ''; ?>>可视化编辑</option>
|
||||
</select>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="admin-card">
|
||||
<form method="post" action="<?php echo site_url('admin/pages/update/' . $p['id']); ?>">
|
||||
<form method="post" action="<?php echo site_url('admin/pages/update/' . $p['id']); ?>" id="fxForm">
|
||||
<?php echo csrf_field(); ?>
|
||||
<input type="hidden" name="mode" value="fixed">
|
||||
<div class="field"><label>标题</label><input name="title" value="<?php echo e($p['title']); ?>"></div>
|
||||
<div class="field"><label>内容(可包含 <p> <b> 等标签)</label><textarea name="content" style="min-height:260px;font-family:monospace"><?php echo e($p['content']); ?></textarea></div>
|
||||
|
||||
<div class="field">
|
||||
<label>正文内容</label>
|
||||
<div class="fx-toolbar">
|
||||
<button type="button" data-cmd="bold" title="加粗"><b>B</b></button>
|
||||
<button type="button" data-cmd="italic" title="斜体"><i>I</i></button>
|
||||
<button type="button" data-cmd="formatBlock" data-val="H2">H2</button>
|
||||
<button type="button" data-cmd="formatBlock" data-val="H3">H3</button>
|
||||
<button type="button" data-cmd="insertUnorderedList" title="无序列表">• 列表</button>
|
||||
<button type="button" data-cmd="insertOrderedList" title="有序列表">1. 列表</button>
|
||||
<button type="button" data-cmd="formatBlock" data-val="BLOCKQUOTE" title="引用">引用</button>
|
||||
<button type="button" id="fxLink" title="插入链接">链接</button>
|
||||
<button type="button" id="fxImg" title="插入图片">图片</button>
|
||||
</div>
|
||||
<div class="fx-editor" id="fxEditor" contenteditable="true"><?php echo $p['content']; ?></div>
|
||||
<textarea name="content" id="fxContent" hidden><?php echo e($p['content']); ?></textarea>
|
||||
<p class="fx-hint">直接排版正文即可;切换「可视化编辑」可自由拖拽布局。保存后页面以统一版式展示。</p>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button class="btn-primary" type="submit">保存</button>
|
||||
<a class="btn-ghost" href="<?php echo site_url('admin/pages'); ?>">取消</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- 图片选择弹层 -->
|
||||
<div class="fx-modal" id="fxModal" hidden>
|
||||
<div class="fx-modal-box">
|
||||
<div class="fx-modal-head"><span>选择图片</span><button type="button" id="fxModalClose">×</button></div>
|
||||
<div class="fx-modal-body">
|
||||
<label class="fx-upload">+ 上传图片<input type="file" id="fxUp" accept="image/*" hidden></label>
|
||||
<div class="fx-lib" id="fxLib"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.mode-switch-sel{display:inline-flex;align-items:center;gap:8px}
|
||||
.mode-switch-sel label{font-size:13px;color:#64748b}
|
||||
.mode-sel{border:1px solid #e2e8f0;border-radius:10px;padding:8px 12px;font-size:14px;background:#fff;color:#334155;cursor:pointer;min-width:140px}
|
||||
.mode-sel:focus{border-color:#0ea5e9;box-shadow:0 0 0 3px rgba(14,165,233,.12)}
|
||||
.mode-badge{display:inline-block;margin-left:10px;padding:2px 10px;border-radius:999px;font-size:12px;font-weight:600;vertical-align:middle;line-height:1.7}
|
||||
.mode-badge.mode-fixed{background:#e0f2fe;color:#0369a1}
|
||||
.mode-badge.mode-builder{background:#ede9fe;color:#6d28d9}
|
||||
.fx-toolbar{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}
|
||||
.fx-toolbar button{width:auto;min-width:38px;height:34px;padding:0 10px;border:1px solid #e2e8f0;background:#fff;border-radius:8px;cursor:pointer;font-size:14px;color:#334155}
|
||||
.fx-toolbar button:hover{border-color:#0ea5e9;color:#0ea5e9}
|
||||
.fx-editor{min-height:320px;border:1px solid #e2e8f0;border-radius:10px;padding:16px 18px;font-size:16px;line-height:1.9;outline:none;background:#fff;overflow:auto}
|
||||
.fx-editor:focus{border-color:#0ea5e9;box-shadow:0 0 0 3px rgba(14,165,233,.12)}
|
||||
.fx-editor h2{font-size:24px;margin:.6em 0 .4em}
|
||||
.fx-editor h3{font-size:20px;margin:.6em 0 .4em}
|
||||
.fx-editor blockquote{margin:.6em 0;padding:8px 14px;border-left:4px solid #0ea5e9;color:#475569;background:#f8fafc}
|
||||
.fx-editor img{max-width:100%;border-radius:8px;display:block;margin:8px 0}
|
||||
.fx-editor a{color:#0ea5e9}
|
||||
.fx-hint{font-size:12px;color:#94a3b8;margin:8px 2px 0}
|
||||
.fx-modal{position:fixed;inset:0;background:rgba(15,23,42,.45);display:flex;align-items:center;justify-content:center;z-index:80}
|
||||
.fx-modal[hidden]{display:none}
|
||||
.fx-modal-box{background:#fff;border-radius:14px;width:420px;max-width:92vw;overflow:hidden}
|
||||
.fx-modal-head{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid #e2e8f0;font-weight:700}
|
||||
.fx-modal-head button{border:none;background:none;font-size:22px;cursor:pointer;color:#64748b;line-height:1}
|
||||
.fx-modal-body{padding:16px;max-height:60vh;overflow:auto}
|
||||
.fx-upload{display:block;text-align:center;background:#0ea5e9;color:#fff;border-radius:10px;padding:10px;cursor:pointer;font-weight:600;margin-bottom:12px}
|
||||
.fx-lib{display:flex;flex-wrap:wrap;gap:8px}
|
||||
.fx-lib img{width:72px;height:72px;object-fit:cover;border-radius:8px;cursor:pointer;border:2px solid transparent}
|
||||
.fx-lib img:hover{border-color:#0ea5e9}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
window.__PB_MEDIA__ = '<?php echo site_url('admin/media'); ?>';
|
||||
window.__PB_UPLOAD__ = '<?php echo site_url('admin/media/upload'); ?>';
|
||||
window.__PB_CSRF__ = '<?php echo csrf_token(); ?>';
|
||||
</script>
|
||||
<script src="<?php echo asset('js/fixed-editor.js'); ?>"></script>
|
||||
|
||||
@@ -3,14 +3,21 @@
|
||||
</div>
|
||||
<div class="admin-card">
|
||||
<table class="admin-table">
|
||||
<tr><th>标识</th><th>标题</th><th>更新时间</th><th>操作</th></tr>
|
||||
<tr><th>标识</th><th>标题</th><th>模式</th><th>更新时间</th><th>操作</th></tr>
|
||||
<?php foreach ($pages as $p): ?>
|
||||
<?php $m = empty($p['mode']) ? 'fixed' : $p['mode']; ?>
|
||||
<tr>
|
||||
<td class="muted"><?php echo e($p['slug']); ?></td>
|
||||
<td><b><?php echo e($p['title']); ?></b></td>
|
||||
<td><span class="mode-badge <?php echo $m === 'builder' ? 'builder' : 'fixed'; ?>"><?php echo $m === 'builder' ? '可视化编辑' : '固定版面'; ?></span></td>
|
||||
<td class="muted"><?php echo e(format_date($p['updated_at'])); ?></td>
|
||||
<td><a class="btn-soft btn-sm" href="<?php echo site_url('admin/pages/edit/' . $p['id']); ?>">编辑</a></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
<style>
|
||||
.mode-badge{display:inline-block;padding:3px 10px;border-radius:999px;font-size:12px;font-weight:600}
|
||||
.mode-badge.fixed{background:#f1f5f9;color:#475569}
|
||||
.mode-badge.builder{background:#e0f2fe;color:#0369a1}
|
||||
</style>
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,46 @@
|
||||
<?php
|
||||
/** @var array $p */
|
||||
/** @var string $mode */
|
||||
$v = function ($k, $d = '') use ($p) { return $p ? ($p[$k] ?? $d) : $d; };
|
||||
$isEdit = !empty($p);
|
||||
$mode = $mode ?? 'fixed';
|
||||
$switchUrl = $isEdit ? site_url('admin/products/switchMode/' . (int)$p['id']) : '';
|
||||
|
||||
$coverVal = $v('cover');
|
||||
$galleryArr = [];
|
||||
$g = $v('gallery');
|
||||
if ($g) { $d = @json_decode($g, true); if (is_array($d)) $galleryArr = $d; }
|
||||
$desc = $v('description');
|
||||
?>
|
||||
<div class="page-head">
|
||||
<div><h1><?php echo $isEdit ? '编辑产品' : '新增产品'; ?></h1><div class="desc">填写产品信息,封面留空将使用渐变占位图</div></div>
|
||||
<a class="btn-ghost" href="<?php echo site_url('admin/products'); ?>">← 返回列表</a>
|
||||
<div>
|
||||
<h1><?php echo $isEdit ? '编辑产品' : '新增产品'; ?><span class="mode-badge mode-fixed">固定版面</span></h1>
|
||||
<div class="desc">固定版面:填写资料并上传封面 / 图集,图片自适应展示<?php echo $isEdit ? ';可切换为可视化自由排版。' : '。'; ?></div>
|
||||
</div>
|
||||
<?php if ($isEdit): ?>
|
||||
<div class="mode-switch-sel">
|
||||
<label for="modeSel">切换模式</label>
|
||||
<select id="modeSel" class="mode-sel" onchange="location.href='<?php echo $switchUrl; ?>?mode='+this.value">
|
||||
<option value="fixed" <?php echo $mode === 'fixed' ? 'selected' : ''; ?>>固定版面</option>
|
||||
<option value="builder" <?php echo $mode === 'builder' ? 'selected' : ''; ?>>可视化编辑</option>
|
||||
</select>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="mode-switch-sel">
|
||||
<label for="modeSel">排版方式</label>
|
||||
<select id="modeSel" class="mode-sel">
|
||||
<option value="fixed" <?php echo $mode === 'fixed' ? 'selected' : ''; ?>>固定版面</option>
|
||||
<option value="builder" <?php echo $mode === 'builder' ? 'selected' : ''; ?>>可视化编辑</option>
|
||||
</select>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="admin-card">
|
||||
<form id="pbForm" method="post" action="<?php echo site_url($isEdit ? 'admin/products/update/' . $p['id'] : 'admin/products/store'); ?>" enctype="multipart/form-data">
|
||||
<form id="fxForm" method="post" action="<?php echo site_url($isEdit ? 'admin/products/update/' . $p['id'] : 'admin/products/store'); ?>" enctype="multipart/form-data">
|
||||
<?php echo csrf_field(); ?>
|
||||
<input type="hidden" name="mode" value="fixed">
|
||||
|
||||
<div class="form-grid">
|
||||
<div class="field">
|
||||
<label>所属分类 *</label>
|
||||
@@ -23,21 +54,44 @@ $isEdit = !empty($p);
|
||||
</div>
|
||||
|
||||
<div class="field"><label>一句话简介</label><input name="summary" value="<?php echo e($v('summary')); ?>"></div>
|
||||
|
||||
<div class="field">
|
||||
<label>详细描述(可视化编辑)</label>
|
||||
<p class="pb-hint" style="margin:0 0 8px">下方为可视化编辑器:上传素材、拖拽文字/图片/按钮自由排版,拖动右下角缩放、双击文字直接编辑。保存后前台按此布局整页展示;可放置「购买按钮 / 价格 / 规格参数」专用块(自动读取本产品数据)。</p>
|
||||
<?php
|
||||
$layoutJson = $v('layout');
|
||||
$layoutArr = $layoutJson ? @json_decode($layoutJson, true) : [];
|
||||
if (!is_array($layoutArr)) $layoutArr = [];
|
||||
echo \Core\View::buffer('admin/parts/builder', ['module' => 'product', 'layout' => $layoutArr]);
|
||||
?>
|
||||
<input type="hidden" name="layout" id="pbLayout">
|
||||
<label>封面图(上传,建议 4:3,将作为列表/详情主图)</label>
|
||||
<input type="file" name="cover" accept="image/*">
|
||||
<?php if ($coverVal): ?>
|
||||
<div class="img-prev"><img src="<?php echo e(site_url($coverVal)); ?>" alt=""><span class="img-prev-path"><?php echo e($coverVal); ?></span></div>
|
||||
<p class="fx-hint">已上传封面;重新选择文件将替换,留空则保留。</p>
|
||||
<?php endif; ?>
|
||||
<input type="text" name="cover_url" value="<?php echo e($coverVal); ?>" placeholder="或填写图片地址/路径 assets/uploads/xxx.jpg 或 http(s)://" style="margin-top:8px">
|
||||
</div>
|
||||
|
||||
<div class="form-grid">
|
||||
<div class="field"><label>封面图(上传,可选)</label><input type="file" name="cover" accept="image/*"></div>
|
||||
<div class="field"><label>或填写图片地址/路径</label><input name="cover_url" value="<?php echo e($v('cover')); ?>" placeholder="assets/uploads/xxx.jpg 或 http(s)://"></div>
|
||||
<div class="field fx-fixed-only">
|
||||
<label>图集(可一次选择多张,每张都会单独上传)</label>
|
||||
<input type="file" name="gallery[]" accept="image/*" multiple>
|
||||
<?php if (!empty($galleryArr)): ?>
|
||||
<div class="gallery-prev">
|
||||
<?php foreach ($galleryArr as $gp): ?><div class="gp-item"><img src="<?php echo e(site_url($gp)); ?>" alt=""><span><?php echo e($gp); ?></span></div><?php endforeach; ?>
|
||||
</div>
|
||||
<label class="chk-inline"><input type="checkbox" name="clear_gallery" value="1"> 清空现有图集(重新上传)</label>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="field fx-fixed-only">
|
||||
<label>详细描述(富文本,每个图片均可上传,前台自适应展示)</label>
|
||||
<div class="fx-toolbar">
|
||||
<button type="button" data-cmd="bold" title="加粗"><b>B</b></button>
|
||||
<button type="button" data-cmd="italic" title="斜体"><i>I</i></button>
|
||||
<button type="button" data-cmd="formatBlock" data-val="H2">H2</button>
|
||||
<button type="button" data-cmd="formatBlock" data-val="H3">H3</button>
|
||||
<button type="button" data-cmd="insertUnorderedList" title="无序列表">• 列表</button>
|
||||
<button type="button" data-cmd="insertOrderedList" title="有序列表">1. 列表</button>
|
||||
<button type="button" data-cmd="formatBlock" data-val="BLOCKQUOTE" title="引用">引用</button>
|
||||
<button type="button" id="fxLink" title="插入链接">链接</button>
|
||||
<button type="button" id="fxImg" title="插入图片">图片</button>
|
||||
</div>
|
||||
<div class="fx-editor" id="fxEditor" contenteditable="true"><?php echo $desc; ?></div>
|
||||
<textarea name="description" id="fxContent" hidden><?php echo e($desc); ?></textarea>
|
||||
<p class="fx-hint">直接排版正文即可;点击「图片」可从素材库选择或上传新图。保存后前台固定版式展示。</p>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
@@ -60,3 +114,86 @@ $isEdit = !empty($p);
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- 图片选择弹层 -->
|
||||
<div class="fx-modal" id="fxModal" hidden>
|
||||
<div class="fx-modal-box">
|
||||
<div class="fx-modal-head"><span>选择图片</span><button type="button" id="fxModalClose">×</button></div>
|
||||
<div class="fx-modal-body">
|
||||
<label class="fx-upload">+ 上传图片<input type="file" id="fxUp" accept="image/*" hidden></label>
|
||||
<div class="fx-lib" id="fxLib"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.mode-switch-sel{display:inline-flex;align-items:center;gap:8px}
|
||||
.mode-switch-sel label{font-size:13px;color:#64748b}
|
||||
.mode-sel{border:1px solid #e2e8f0;border-radius:10px;padding:8px 12px;font-size:14px;background:#fff;color:#334155;cursor:pointer;min-width:140px}
|
||||
.mode-sel:focus{border-color:#0ea5e9;box-shadow:0 0 0 3px rgba(14,165,233,.12)}
|
||||
.mode-badge{display:inline-block;margin-left:10px;padding:2px 10px;border-radius:999px;font-size:12px;font-weight:600;vertical-align:middle;line-height:1.7}
|
||||
.mode-badge.mode-fixed{background:#e0f2fe;color:#0369a1}
|
||||
.mode-badge.mode-builder{background:#ede9fe;color:#6d28d9}
|
||||
.img-prev{display:flex;align-items:center;gap:10px;margin-top:10px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:8px 10px}
|
||||
.img-prev img{width:72px;height:54px;object-fit:cover;border-radius:8px;display:block}
|
||||
.img-prev-path{font-size:12px;color:#94a3b8;word-break:break-all}
|
||||
.gallery-prev{display:flex;flex-wrap:wrap;gap:10px;margin-top:10px}
|
||||
.gallery-prev .gp-item{width:104px;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden;background:#fff}
|
||||
.gallery-prev .gp-item img{width:100%;height:74px;object-fit:cover;display:block}
|
||||
.gallery-prev .gp-item span{display:block;font-size:11px;color:#94a3b8;padding:4px 6px;word-break:break-all;line-height:1.3}
|
||||
.chk-inline{display:inline-flex;align-items:center;gap:6px;margin-top:10px;font-size:13px;color:#64748b;cursor:pointer}
|
||||
.fx-toolbar{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}
|
||||
.fx-toolbar button{width:auto;min-width:38px;height:34px;padding:0 10px;border:1px solid #e2e8f0;background:#fff;border-radius:8px;cursor:pointer;font-size:14px;color:#334155}
|
||||
.fx-toolbar button:hover{border-color:#0ea5e9;color:#0ea5e9}
|
||||
.fx-editor{min-height:260px;border:1px solid #e2e8f0;border-radius:10px;padding:16px 18px;font-size:16px;line-height:1.9;outline:none;background:#fff;overflow:auto}
|
||||
.fx-editor:focus{border-color:#0ea5e9;box-shadow:0 0 0 3px rgba(14,165,233,.12)}
|
||||
.fx-editor h2{font-size:24px;margin:.6em 0 .4em}
|
||||
.fx-editor h3{font-size:20px;margin:.6em 0 .4em}
|
||||
.fx-editor blockquote{margin:.6em 0;padding:8px 14px;border-left:4px solid #0ea5e9;color:#475569;background:#f8fafc}
|
||||
.fx-editor img{max-width:100%;height:auto;border-radius:8px;display:block;margin:8px 0}
|
||||
.fx-editor a{color:#0ea5e9}
|
||||
.fx-hint{font-size:12px;color:#94a3b8;margin:8px 2px 0}
|
||||
.fx-modal{position:fixed;inset:0;background:rgba(15,23,42,.45);display:flex;align-items:center;justify-content:center;z-index:80}
|
||||
.fx-modal[hidden]{display:none}
|
||||
.fx-modal-box{background:#fff;border-radius:14px;width:420px;max-width:92vw;overflow:hidden}
|
||||
.fx-modal-head{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid #e2e8f0;font-weight:700}
|
||||
.fx-modal-head button{border:none;background:none;font-size:22px;cursor:pointer;color:#64748b;line-height:1}
|
||||
.fx-modal-body{padding:16px;max-height:60vh;overflow:auto}
|
||||
.fx-upload{display:block;text-align:center;background:#0ea5e9;color:#fff;border-radius:10px;padding:10px;cursor:pointer;font-weight:600;margin-bottom:12px}
|
||||
.fx-lib{display:flex;flex-wrap:wrap;gap:8px}
|
||||
.fx-lib img{width:72px;height:72px;object-fit:cover;border-radius:8px;cursor:pointer;border:2px solid transparent}
|
||||
.fx-lib img:hover{border-color:#0ea5e9}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
window.__PB_MEDIA__ = '<?php echo site_url('admin/media'); ?>';
|
||||
window.__PB_UPLOAD__ = '<?php echo site_url('admin/media/upload'); ?>';
|
||||
window.__PB_CSRF__ = '<?php echo csrf_token(); ?>';
|
||||
</script>
|
||||
<script src="<?php echo asset('js/fixed-editor.js'); ?>"></script>
|
||||
<script>
|
||||
// 新增产品时按「排版方式」选择器联动:选可视化编辑则隐藏图集/详细描述,并提示保存后进入可视化编辑器
|
||||
(function(){
|
||||
var sel = document.getElementById('modeSel');
|
||||
if(!sel) return;
|
||||
var isCreate = <?php echo $isEdit ? 'false' : 'true'; ?>;
|
||||
var modeField = document.querySelector('#fxForm input[name="mode"]');
|
||||
var fixedOnly = document.querySelectorAll('.fx-fixed-only');
|
||||
var note = document.createElement('p');
|
||||
note.className = 'fx-hint fx-builder-note';
|
||||
note.style.cssText = 'margin-top:10px;color:#6d28d9;background:#f5f3ff;border:1px solid #ddd6fe;border-radius:8px;padding:8px 12px;display:none';
|
||||
note.textContent = '已选择「可视化编辑」:图集与详细描述无需填写,保存后将进入可视化编辑器排版产品详情。';
|
||||
var firstFixed = fixedOnly[0];
|
||||
if(firstFixed && firstFixed.parentNode){ firstFixed.parentNode.insertBefore(note, firstFixed); }
|
||||
function apply(){
|
||||
var m = sel.value;
|
||||
if(modeField) modeField.value = m;
|
||||
if(!isCreate) return; // 编辑页选择器仅用于切换页面,不在此隐藏字段
|
||||
var isBuilder = (m === 'builder');
|
||||
for(var i=0;i<fixedOnly.length;i++){ fixedOnly[i].style.display = isBuilder ? 'none' : ''; }
|
||||
note.style.display = isBuilder ? 'block' : 'none';
|
||||
}
|
||||
sel.addEventListener('change', apply);
|
||||
apply();
|
||||
})();
|
||||
</script>
|
||||
|
||||
@@ -9,13 +9,15 @@ $cmap = []; foreach ($cm->all() as $c) $cmap[$c['id']] = $c['name'];
|
||||
|
||||
<div class="admin-card">
|
||||
<table class="admin-table">
|
||||
<tr><th>封面</th><th>名称</th><th>分类</th><th>价格</th><th>状态</th><th>操作</th></tr>
|
||||
<tr><th>封面</th><th>名称</th><th>分类</th><th>价格</th><th>模式</th><th>状态</th><th>操作</th></tr>
|
||||
<?php foreach ($products as $p): ?>
|
||||
<?php $pm = empty($p['mode']) ? 'fixed' : $p['mode']; ?>
|
||||
<tr>
|
||||
<td><div class="thum" style="background:<?php echo gradient($p['id']); ?>">❄</div></td>
|
||||
<td><?php if (!empty($p['cover'])): ?><div class="thum" style="background:#fff"><img src="<?php echo e(site_url($p['cover'])); ?>" alt="" style="width:100%;height:100%;object-fit:cover;border-radius:10px"></div><?php else: ?><div class="thum" style="background:<?php echo gradient($p['id']); ?>">❄</div><?php endif; ?></td>
|
||||
<td><b><?php echo e($p['name']); ?></b><br><span class="muted" style="font-size:12px"><?php echo e($p['slug']); ?></span></td>
|
||||
<td><?php echo e($cmap[$p['category_id']] ?? '—'); ?></td>
|
||||
<td>¥<?php echo e($p['price']); ?></td>
|
||||
<td><span class="mode-badge <?php echo $pm === 'builder' ? 'builder' : 'fixed'; ?>"><?php echo $pm === 'builder' ? '可视化编辑' : '固定版面'; ?></span></td>
|
||||
<td><?php echo ($p['status'] ?? 1) ? '<span class="tag-mini">已上线</span>' : '<span class="muted">草稿</span>'; ?></td>
|
||||
<td>
|
||||
<div class="row-actions">
|
||||
@@ -26,4 +28,9 @@ $cmap = []; foreach ($cm->all() as $c) $cmap[$c['id']] = $c['name'];
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
<style>
|
||||
.mode-badge{display:inline-block;padding:3px 10px;border-radius:999px;font-size:12px;font-weight:600}
|
||||
.mode-badge.fixed{background:#f1f5f9;color:#475569}
|
||||
.mode-badge.builder{background:#e0f2fe;color:#0369a1}
|
||||
</style>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div><h1>站点设置</h1><div class="desc">网站名称、联系方式与 SEO 信息</div></div>
|
||||
</div>
|
||||
<div class="admin-card">
|
||||
<form method="post" action="<?php echo site_url('admin/settings'); ?>">
|
||||
<form method="post" action="<?php echo site_url('admin/settings'); ?>" enctype="multipart/form-data">
|
||||
<?php echo csrf_field(); ?>
|
||||
<div class="form-grid">
|
||||
<div class="field"><label>网站名称</label><input name="site_name" value="<?php echo e($v['site_name']); ?>"></div>
|
||||
@@ -11,7 +11,14 @@
|
||||
<div class="field"><label>联系邮箱</label><input name="contact_email" value="<?php echo e($v['contact_email']); ?>"></div>
|
||||
</div>
|
||||
<div class="field"><label>联系地址</label><input name="contact_address" value="<?php echo e($v['contact_address']); ?>"></div>
|
||||
<div class="field"><label>备案号</label><input name="icp" value="<?php echo e($v['icp']); ?>"></div>
|
||||
<div class="field" style="grid-column:1/-1">
|
||||
<label>网站 Logo(酷冰甲商标)</label>
|
||||
<input type="file" name="logo" accept="image/*">
|
||||
<small style="color:#888;display:block;margin-top:4px">选择图片上传将替换当前 Logo;也可在下方直接填写图片路径或网址(留空则保留现有)。当前:<?php echo e($v['site_logo'] ?: '默认商标'); ?></small>
|
||||
<input type="text" name="logo_url" value="<?php echo e($v['site_logo']); ?>" placeholder="图片路径或网址,如 assets/img/logo.png 或 https://...">
|
||||
</div>
|
||||
<div class="field"><label>备案号(ICP)</label><input name="icp" value="<?php echo e($v['icp']); ?>" placeholder="如 苏ICP备XXXXXXXX号"></div>
|
||||
<div class="field"><label>公安备案号(网安备)</label><input name="gongan" value="<?php echo e($v['gongan'] ?? ''); ?>" placeholder="如 京公网安备11010802012345号"></div>
|
||||
<hr style="border:none;border-top:1px solid #eef2f7;margin:18px 0">
|
||||
<div class="field"><label>SEO 标题</label><input name="seo_title" value="<?php echo e($v['seo_title']); ?>"></div>
|
||||
<div class="field"><label>SEO 关键词</label><input name="seo_keywords" value="<?php echo e($v['seo_keywords']); ?>"></div>
|
||||
|
||||
Reference in New Issue
Block a user