14 lines
10 KiB
HTML
14 lines
10 KiB
HTML
|
|
<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>SiteForge Studio V8.23 · 嵌套组件编辑</title><style>
|
|||
|
|
*{box-sizing:border-box}body{margin:0;background:#f3f5f8;color:#263447;font:14px system-ui,-apple-system,'Microsoft YaHei',sans-serif}button,input,select{font:inherit}button{cursor:pointer}header{height:70px;display:flex;align-items:center;gap:16px;padding:0 22px;background:white;border-bottom:1px solid #e3e8ef}header strong{font-size:19px}header small{color:#8795a6}header .sep{flex:1}header button{border:1px solid #e0e5eb;border-radius:8px;padding:9px 15px;background:white;color:#34485e}header .save{background:#ec772f;border-color:#ec772f;color:#fff;font-weight:750}.step{padding:11px 25px;background:#fff8f2;border-bottom:1px solid #f1d9c4;color:#ad642e;font-weight:700}main{display:grid;grid-template-columns:246px minmax(0,1fr) 290px;height:calc(100vh - 112px);min-height:620px}aside{background:#fff;overflow-y:auto;padding:21px;border-right:1px solid #e7eaf0}aside:last-child{border-right:0;border-left:1px solid #e7eaf0}h3{margin:0 0 20px;font-size:16px}p.hint{color:#8995a6;font-size:12px;line-height:1.7;margin-top:6px}.group{margin:16px 0 9px;color:#8b99a9;font-size:11px;font-weight:800;letter-spacing:1px}select,input{border:1px solid #dce3ed;border-radius:8px;padding:10px;width:100%;background:white;color:#293d55}.navitem,.childlist{border:1px solid #e3e9f0;border-radius:9px;padding:11px;margin-bottom:8px;background:#fbfcfe;cursor:pointer}.navitem.selected,.childlist.selected{border-color:#e98037;background:#fff8f2}.navitem small,.childlist small{display:block;color:#8898a6;margin-top:5px}.add{width:100%;margin-top:13px;background:#e8782f;color:white;padding:12px;border:0;border-radius:9px;font-weight:800}.canvas-shell{display:flex;flex-direction:column;min-width:0}.canvas-head{background:#fff;height:51px;display:flex;align-items:center;justify-content:space-between;padding:0 24px;border-bottom:1px solid #e7ebf0;font-size:12px;color:#77879a}.switch button{background:#f1f4f8;padding:8px 10px;border:0;border-radius:6px;margin:0 2px;color:#63768a}.switch button.on{background:#ed7e37;color:#fff}.stage{flex:1;overflow:auto;padding:28px;background:radial-gradient(#d6dde8 1px,transparent 1px);background-size:20px 20px}.page{margin:auto;max-width:1050px;min-width:0;background:white;box-shadow:0 12px 48px #2437471c;transition:width .2s}.page.phone{width:min(390px,100%)}.page.tablet{width:min(780px,100%)}.sitehead{height:70px;border-bottom:1px solid #e7e7e7;display:flex;align-items:center;justify-content:space-between;padding:0 7%;color:#25364d}.logo{font-size:18px;font-weight:900;color:#e8752f}.sitehead small{font-size:12px;color:#6f7e8d}.hero{padding:40px 7% 22px}.hero h1{font-size:clamp(25px,3vw,36px);margin:0 0 8px}.hero p{color:#8793a1;margin:0}.layout{padding:12px 7% 60px;display:grid;gap:16px;grid-template-columns:var(--cols,1fr 1fr)}.page.phone .layout{grid-template-columns:1fr!important}.page.tablet .layout{grid-template-columns:1fr 1fr}.unit{border:2px dashed transparent;background:#f5f7fa;min-height:125px;border-radius:12px;padding:20px 17px;cursor:pointer;position:relative;overflow:visible}.unit:hover{border-color:#e8b48e}.unit.active{border-color:#e8752f;background:#fffaf6}.unit h2{font-size:18px;margin:12px 0 8px}.unit p{color:#7c8b9b;font-size:13px;line-height:1.65}.unit b{font-size:11px;color:#e27530}.unit .mini{display:none;gap:4px;position:absolute;right:7px;top:7px;z-index:2}.unit:hover .mini,.unit.active .mini{display:flex}.mini button{font-size:11px;border:0;background:#34465a;color:#fff;border-radius:5px;padding:5px 7px}.placeholder{background:linear-gradient(135deg,#f7d2aa,#e9edf5);height:100px;border-radius:6px;margin:6px 0}.ctrl{margin-bottom:17px}.ctrl label{display:block;font-size:12px;color:#78899b;font-weight:750;margin-bottom:7px}.ctrl input{font-size:13px}.buttons{display:flex;gap:6px;flex-wrap:wrap}.buttons button{background:#fff8f1;color:#965522;border:1px solid #edc9aa;border-radius:7px;font-size:11px;padding:8px 10px}.buttons button:hover{background:#ffe9d8}.notice{font-size:12px;color:#ba712d;background:#fff4e9;padding:10px 12px;border-radius:9px;line-height:1.6}.meta{padding:12px 25px;color:#8
|
|||
|
|
</style></head><body>
|
|||
|
|
<header><strong><span style="color:#ea792e">◈</span> SiteForge Studio</strong><small>V8.23 · 嵌套画布编辑演示</small><span class="sep"></span><span id="status" style="font-size:12px;color:#8392a1">演示草稿</span><button onclick="undo()">↶ 撤销</button><button onclick="save()" class="save">保存草稿</button></header>
|
|||
|
|
<div class="step">① 点击画布中的组件 → ② 直接编辑右侧内容或选择布局 → ③ 保存草稿</div>
|
|||
|
|
<main><aside><h3>页面内容</h3><label style="font-size:12px;color:#70839a">当前页面</label><select><option>首页 /</option></select><div class="group">页面结构</div><div class="navitem">▤ 封面横幅<small>网站主标题</small></div><div class="navitem selected">▥ 双列布局<small>可编辑下面的列内组件</small></div><div id="tree"></div><button class="add" onclick="add()">+ 在本列新增组件</button><p class="hint">此页面使用本地演示数据。实际系统具备草稿、版本校验与构建接口。</p></aside>
|
|||
|
|
<div class="canvas-shell"><div class="canvas-head"><span>● 可视化预览 · 点击卡片直接编辑</span><span class="switch"><button class="on" onclick="device('desktop',this)">电脑</button><button onclick="device('tablet',this)">平板</button><button onclick="device('phone',this)">手机</button></span></div><div class="stage"><div class="page" id="page"><div class="sitehead"><span class="logo">HESU AUTO</span><small>HOME VEHICLES ABOUT CONTACT ☰</small></div><div class="hero"><h1>China Sourcing. Global Delivery.</h1><p>拖动布局、点击组件、修改文字,立即看到页面变化。</p></div><div class="layout" id="layout"></div></div></div><div class="meta">画布修改只影响演示数据 · 不会连接、修改或发布正式网站</div></div>
|
|||
|
|
<aside><h3>编辑选中的组件</h3><div id="selectedInfo" class="notice">点击中间任一组件开始编辑。</div><div class="group">内容</div><div class="ctrl"><label>组件标题</label><input id="title" oninput="field('title',this.value)" placeholder="请输入标题"></div><div class="ctrl"><label>说明文字</label><input id="description" oninput="field('description',this.value)" placeholder="请输入简介"></div><div class="group">列宽布局</div><div class="buttons"><button onclick="preset('equal')">等宽两列</button><button onclick="preset('left')">左宽右窄</button><button onclick="preset('right')">左窄右宽</button></div><p class="hint">手机布局独立显示为单列,不会覆盖电脑端的列宽设置。</p><div class="group">组件操作</div><div class="buttons"><button onclick="duplicate()">复制组件</button><button onclick="up()">上移</button><button onclick="remove()">删除</button></div></aside></main>
|
|||
|
|
<script>
|
|||
|
|
const data=[{id:1,title:'车辆采购',description:'严格筛选、全球品牌、稳定采购渠道',col:0},{id:2,title:'国际物流',description:'集装箱、滚装及多式联运方案',col:1},{id:3,title:'海外交付',description:'海外网络、本地服务与配件支持',col:0}];let state={rows:data,selected:1,preset:'equal'},history=[];
|
|||
|
|
const $=id=>document.getElementById(id);const esc=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));function snapshot(){history.push(JSON.stringify(state));if(history.length>25)history.shift()};function changed(){document.querySelector('#status').textContent='有未保存的修改';draw()}
|
|||
|
|
function draw(){const col=state.preset==='left'?'2fr 1fr':state.preset==='right'?'1fr 2fr':'1fr 1fr';$('layout').style.setProperty('--cols',col);const buckets=[[],[]];state.rows.forEach(r=>buckets[r.col].push(r));$('layout').innerHTML=buckets.map((items,ci)=>`<div>${items.map(r=>`<section class="unit ${state.selected===r.id?'active':''}" onclick="select(${r.id})"><div class="mini"><button onclick="event.stopPropagation();select(${r.id})">✎</button><button onclick="event.stopPropagation();clone(${r.id})">⧉</button><button onclick="event.stopPropagation();drop(${r.id})">×</button></div><b>第 ${ci+1} 列 · 内容组件</b><h2>${esc(r.title)}</h2><p>${esc(r.description)}</p></section>`).join('')}</div>`).join('');$('tree').innerHTML=state.rows.map(r=>`<div class="childlist ${state.selected===r.id?'selected':''}" onclick="select(${r.id})">第${r.col+1}列 · ${esc(r.title)}<small>点击选中后编辑</small></div>`).join('');const item=state.rows.find(r=>r.id===state.selected);$('selectedInfo').textContent=item?'已选择:'+item.title:'请先点击一个组件';$('title').value=item?.title||'';$('description').value=item?.description||'';}
|
|||
|
|
function select(id){state.selected=id;draw()}function field(k,v){const r=state.rows.find(r=>r.id===state.selected);if(!r)return;r[k]=v;changed()}function preset(v){snapshot();state.preset=v;changed()}function clone(id){const r=state.rows.find(r=>r.id===id);if(!r)return;snapshot();const next={...r,id:Math.max(0,...state.rows.map(x=>x.id))+1};state.rows.push(next);state.selected=next.id;changed()}function duplicate(){clone(state.selected)}function drop(id){snapshot();state.rows=state.rows.filter(r=>r.id!==id);state.selected=state.rows[0]?.id||null;changed()}function remove(){drop(state.selected)}function up(){const i=state.rows.findIndex(x=>x.id===state.selected);if(i<1)return;snapshot();[state.rows[i-1],state.rows[i]]=[state.rows[i],state.rows[i-1]];changed()}function add(){snapshot();const selected=state.rows.find(r=>r.id===state.selected);const n={id:Math.max(0,...state.rows.map(x=>x.id))+1,title:'新内容组件',description:'点击右侧填写内容',col:selected?.col||0};state.rows.push(n);state.selected=n.id;changed()}function undo(){if(!history.length)return;state=JSON.parse(history.pop());changed()}function save(){$('status').textContent='演示草稿已保存(仅当前页面)'}function device(name,button){$('page').className='page '+(name==='desktop'?'':name);document.querySelectorAll('.switch button').forEach(b=>b.classList.toggle('on',b===button))}draw();</script></body></html>
|