diff --git a/app/static/admin.js b/app/static/admin.js index dbb935e..9dd58dc 100644 --- a/app/static/admin.js +++ b/app/static/admin.js @@ -2,7 +2,7 @@ const $=(q,el=document)=>el.querySelector(q); const E=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); const ATTR=s=>E(s); -const cfg={automotive:{label:'汽车与出行',desc:'高级质感 · 深色车型展厅',prev:'auto',title:'Move beyond.'},industrial:{label:'工业制造',desc:'专业理性 · 工业产品展示',prev:'ind',title:'Built to last.'},corporate:{label:'企业品牌',desc:'现代明亮 · 集团企业官网',prev:'corp',title:'Ideas become impact.'},minimal:{label:'极简设计',desc:'编辑式排版 · 极简作品展示',prev:'min',title:'Less, but better.'}}; +const cfg={automotive:{label:'汽车与出行',desc:'高级质感 · 深色车型展厅',prev:'auto',title:'Move beyond.'},industrial:{label:'工业制造',desc:'专业理性 · 工业产品展示',prev:'ind',title:'Built to last.'},corporate:{label:'企业品牌',desc:'现代明亮 · 集团企业官网',prev:'corp',title:'Ideas become impact.'},minimal:{label:'极简设计',desc:'编辑式排版 · 极简作品展示',prev:'min',title:'Less, but better.'},'trade-pro':{label:'Trade Pro',desc:'英文外贸 · B2B 目录与询盘',prev:'corp',title:'Go global.'}}; let csrfToken=''; const state={sites:[],siteId:null,site:null,entries:[],builds:[],tab:'overview',presets:[],query:'',typ:''}; const api=async(path,opt={})=>{ diff --git a/app/static/factory-v2.js b/app/static/factory-v2.js index c76f162..b8d5071 100644 --- a/app/static/factory-v2.js +++ b/app/static/factory-v2.js @@ -27,7 +27,7 @@ async function overview(){let [entries,builds,source]=await Promise.all([api(sit

网站工厂生产流程

01网站结构首页、栏目页和导航
02内容自动装配导入新数据或旧内容
03设计编辑切换主题、可视化编辑
04静态站交付构建、验收、发布

网站页面

${entries.slice(0,25).map(x=>``).join('')}
页面/内容类型URL操作
${H(x.title)}${H(x.type)}${H(x.route)}设计页面 ↗

联系信息与表单服务

邮箱会出现在主题的联系页与页脚。外部表单地址为空时,不显示假提交按钮。

常用功能

当没有真实产品时,主题不会虚构业务数据;可先完善基础页面,再逐步导入。

`;} async function bootstrap(){try{let r=await api(factoryUrl('/bootstrap'),'POST',{});toast(`新增 ${r.created.length} 个基础页面;不会覆盖原 URL`);await render()}catch(e){toast(e.message,true)}} -async function themes(){let cur=await api(factoryUrl('/theme'));const schemes={automotive:['#172840','#cfab79','MOVE BEYOND'],industrial:['#dcebf4','#14517d','BUILD FURTHER'],corporate:['#e7e9fb','#535bb4','CREATE IMPACT'],minimal:['#e9e5dc','#3d3b35','LESS IS MORE']}; +async function themes(){let cur=await api(factoryUrl('/theme'));const schemes={automotive:['#172840','#cfab79','MOVE BEYOND'],industrial:['#dcebf4','#14517d','BUILD FURTHER'],corporate:['#e7e9fb','#535bb4','CREATE IMPACT'],minimal:['#e9e5dc','#3d3b35','LESS IS MORE'],'trade-pro':['#0b3d91','#e8f1fb','GO GLOBAL']}; $('#panel').innerHTML=`

可安装、可版本化的主题包

当前主题:${H(cur.theme)} · v${H(cur.version)}
${state.themes.map(t=>{let id=t.id||t.theme_id,p=schemes[id]||['#e9eff8','#246c9e','YOUR BRAND'];return `
${H(p[2])}

${H(t.name)} v${H(t.version)}

${H(t.description)}

全部页面预览首页预览
`}).join('')}

安装新主题 ZIP

主题包由 manifest.json、theme.css、page-presets.json 组成。只能安装受控的页面组件和 CSS,不执行上传的 JavaScript 或模板逻辑。

批量重装配现有内容

会按页面类型给已有内容应用当前主题;保留现有 URL、SEO 和正文。选择「只补缺失」可避免覆盖已手工设计的区块。

`;} async function chooseTheme(id,version){if(!confirm(`为当前网站选择主题 ${id} v${version}?将保留网站内容。`))return;try{await api(factoryUrl('/theme'),'PUT',{theme:id,version});await refresh();toast('主题切换完成。需要重新构建才能更新正式网站');await render()}catch(e){toast(e.message,true)}} diff --git a/app/static/workspace.js b/app/static/workspace.js index d7aaf6f..e4eb176 100644 --- a/app/static/workspace.js +++ b/app/static/workspace.js @@ -2,7 +2,7 @@ /* SiteForge simplified workspace: native APIs, no parallel business backend. */ const $=(s,root=document)=>root.querySelector(s); const esc=x=>String(x??'').replace(/[&<>"']/g,ch=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[ch])); -const themeName={automotive:'汽车与出行',industrial:'工业与制造',corporate:'企业品牌',minimal:'极简展示'}; +const themeName={automotive:'汽车与出行',industrial:'工业与制造',corporate:'企业品牌',minimal:'极简展示','trade-pro':'Trade Pro'}; const typeName={page:'页面',product:'产品',vehicle:'车型',post:'新闻',brand:'品牌',case:'案例',service:'服务'}; const fmtDate=t=>{if(!t)return '—';const d=new Date(t);return Number.isNaN(d.getTime())?String(t).slice(0,16):d.toLocaleDateString('zh-CN',{year:'numeric',month:'2-digit',day:'2-digit'})}; const sfSiteKey='siteforge:selected-site'; diff --git a/app/templates/admin.html b/app/templates/admin.html index 3b8b48b..bbde95d 100644 --- a/app/templates/admin.html +++ b/app/templates/admin.html @@ -10,6 +10,6 @@
-
CREATE WEBSITE

创建全新网站

选择模板并创建站点,后续可继续导入旧内容或添加新数据。

+
CREATE WEBSITE

创建全新网站

选择模板并创建站点,后续可继续导入旧内容或添加新数据。

CONTENT EDITOR

新增页面 / 内容

所有字段均属于当前网站,修改后重新构建即可更新静态文件。

首页区块快捷添加基础区块使用 JSON 配置;进入「可视化页面设计」可进行拖动排序和属性调整。
V8 网站生产控制台 → diff --git a/app/templates/theme-gallery.html b/app/templates/theme-gallery.html index 5b437d1..35ce1bf 100644 --- a/app/templates/theme-gallery.html +++ b/app/templates/theme-gallery.html @@ -1,7 +1,7 @@ SiteForge · 完整主题预览中心
SF SiteForge · 主题预览中心返回网站工厂 →
-
+
预览失败,请确认已登录。
diff --git a/app/templates/workspace.html b/app/templates/workspace.html index 112a0dc..be67c9f 100644 --- a/app/templates/workspace.html +++ b/app/templates/workspace.html @@ -38,6 +38,6 @@
+
diff --git a/app/theme_pro.py b/app/theme_pro.py index 8a34a4b..cd2f16e 100644 --- a/app/theme_pro.py +++ b/app/theme_pro.py @@ -184,7 +184,7 @@ def make_context(site,page,records,mode='detail',listing_items=None,prepared=Non if chrome['nav']:nav=chrome['nav'] form_endpoint=settings.get('form_endpoint') or '' form_endpoint=form_endpoint if isinstance(form_endpoint,str) and form_endpoint.startswith('https://') and not any(x in form_endpoint for x in ('<','>','\"','\n')) else '' - return {'year':datetime.datetime.now(datetime.timezone.utc).year,'theme_color':{'automotive':'#0e1c2c','industrial':'#113f59','corporate':'#f5f6fa','minimal':'#f8f7f3'}.get(site.get('theme'),'#ffffff'),'gallery':media_gallery(pg),'form_endpoint':form_endpoint,'site':site,'page':pg,'kind':kind,'records':records,'groups':groups,'listing':listing, + return {'year':datetime.datetime.now(datetime.timezone.utc).year,'theme_color':{'automotive':'#0e1c2c','industrial':'#113f59','corporate':'#f5f6fa','minimal':'#f8f7f3','trade-pro':'#0b3d91'}.get(site.get('theme'),'#ffffff'),'gallery':media_gallery(pg),'form_endpoint':form_endpoint,'site':site,'page':pg,'kind':kind,'records':records,'groups':groups,'listing':listing, 'showcase':groups['product'][:6]+groups['vehicle'][:max(0,6-len(groups['product'][:6]))], 'features':groups['service'][:3], 'stories':groups['post'][:3], 'cases':groups['case'][:3], 'brands':assets['brands'],'categories':assets['categories'], 'nav':nav, diff --git a/tests/test_theme_registry.py b/tests/test_theme_registry.py index 1a03222..8b812a2 100644 --- a/tests/test_theme_registry.py +++ b/tests/test_theme_registry.py @@ -114,6 +114,30 @@ def test_trade_pro_builds_real_site(factory): assert '>首页<' not in home.text assert '{{ seo_title }}{% if canonical %}{% endif %}{# Skeleton: hard-coded theme color; switch back to the theme_color context variable once the platform map gains a trade-pro entry (Task 6). #}{% if canonical and not noindex %}{% endif %}{% if theme_overrides %}{% endif %}Skip to content +{{ seo_title }}{% if canonical %}{% endif %}{% if canonical and not noindex %}{% endif %}{% if theme_overrides %}{% endif %}Skip to content {% from '_professional_components.html' import card,cover,grid,section_title,filters,footer_links,body_copy with context %} {# English fallback navigation (skeleton): the platform always fills nav with Chinese defaults (首页/产品/品牌/新闻/案例/关于/联系) unless the site configured