feat: unified form block + Contact page matches CMS (info+form+map+FAQ)
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import json, re, uuid, urllib.request, http.cookiejar
|
||||
from pathlib import Path
|
||||
|
||||
pw = re.search(r'SITEFORGE_ADMIN_PASSWORD=(.+)', Path('.env').read_text()).group(1).strip()
|
||||
cj = http.cookiejar.CookieJar()
|
||||
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
|
||||
BASE = 'http://127.0.0.1:8787'
|
||||
sid = '483295c29ea0'
|
||||
opener.open(urllib.request.Request(BASE+'/api/auth/login',
|
||||
data=json.dumps({'username':'admin','password':pw}).encode(),
|
||||
headers={'Content-Type':'application/json'}))
|
||||
csrf = json.load(opener.open(BASE+'/api/auth/me'))['csrf']
|
||||
|
||||
gmaps = 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3276.4503537870382!2d113.59874507574851!3d34.79460997288641!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x35d764e14634544d%3A0x2fcba85c7824cd78!2sHe%27Nan+Province+National+University+Science+Park+(East+Zone)+17+Building+Parking+Lot!5e0!3m2!1sen!2sjp!4v1714461571915!5m2!1sen!2sjp'
|
||||
|
||||
blocks = [
|
||||
{'id':uuid.uuid4().hex[:10],'type':'hero','visible':True,
|
||||
'title':'Contact Us','subtitle':'GET IN TOUCH',
|
||||
'description':'We respond within one business day.',
|
||||
'image':'','button':'','href':'','align':'left','layout_variant':'split','image_fit':'cover'},
|
||||
{'id':uuid.uuid4().hex[:10],'type':'image_text','visible':True,
|
||||
'title':'Sales Team','subtitle':'TALK TO US',
|
||||
'description':'Our international sales team helps with product selection, pricing and shipping. Email us for catalogs and quotations.',
|
||||
'image':'','image_side':'left','button':'Email Us','href':'mailto:sales@hesupipe.com'},
|
||||
{'id':uuid.uuid4().hex[:10],'type':'form','visible':True,
|
||||
'title':'Get a Quote',
|
||||
'description':'Send us your requirements and our team will reply within 24 hours.',
|
||||
'button_text':'Contact Us','button_href':'/contact-us/'},
|
||||
{'id':uuid.uuid4().hex[:10],'type':'map','visible':True,
|
||||
'title':'Visit Our Office',
|
||||
'address':'Henan Province National University Science Park (East Zone) 17 Building, Zhengzhou, China',
|
||||
'url':'','embed':gmaps},
|
||||
{'id':uuid.uuid4().hex[:10],'type':'faq','visible':True,
|
||||
'title':'Frequently Asked Questions',
|
||||
'items':[
|
||||
{'question':'How can I get a quotation?','answer':'Send us your requirements via email or the inquiry form.'},
|
||||
{'question':'What is your MOQ?','answer':'MOQ varies by product. Contact us for details.'},
|
||||
{'question':'Do you provide samples?','answer':'Yes, samples available for evaluation.'}]},
|
||||
]
|
||||
|
||||
eid = 'a4992289f61b'
|
||||
d = json.load(opener.open(BASE+'/api/sites/'+sid+'/pages/'+eid+'/studio-draft'))
|
||||
req = urllib.request.Request(BASE+'/api/sites/'+sid+'/pages/'+eid+'/studio-draft',
|
||||
data=json.dumps({'blocks':blocks,'page_template':'contact','layout_mode':'replace','expected_revision':d['revision']}).encode(),
|
||||
method='PUT', headers={'Content-Type':'application/json','X-SiteForge-CSRF':csrf})
|
||||
r = json.load(opener.open(req))
|
||||
req2 = urllib.request.Request(BASE+'/api/sites/'+sid+'/pages/'+eid+'/studio-draft/publish',
|
||||
data=json.dumps({'expected_revision':r.get('revision',d['revision']+1)}).encode(), method='POST',
|
||||
headers={'Content-Type':'application/json','X-SiteForge-CSRF':csrf})
|
||||
print('Contact updated:', json.load(opener.open(req2)).get('published'))
|
||||
@@ -27,6 +27,7 @@ BLOCKS = {
|
||||
'pricing':{'name':'服务方案','icon':'$','fields':['title','items'],'defaults':{'title':'服务方案','items':[{'name':'标准方案','price':'联系我们','features':['专业咨询','售后服务'],'href':'/contact/'}]}},
|
||||
'map':{'name':'位置导航','icon':'⌖','fields':['title','address','url','embed'],'defaults':{'title':'欢迎来访','address':'请填写实际办公地址','url':'','embed':''}},
|
||||
'form_link':{'name':'询盘表单入口','icon':'✉','fields':['title','description','button','href'],'defaults':{'title':'提交询盘','description':'欢迎联系我们获取报价和资料','button':'联系销售','href':'/contact/'}},
|
||||
'form':{'name':'询盘表单','icon':'✉','fields':['title','description','button_text','button_href'],'defaults':{'title':'Get a Quote','description':'Send us your requirements and our team will reply within 24 hours.','button_text':'Contact Us','button_href':'/contact-us/'}},
|
||||
'trust_bar':{'name':'信任条','icon':'✓','fields':['title','items'],'defaults':{'title':'','items':[{'icon':'✓','title':'Certified quality','text':'Inspected before every shipment'},{'icon':'◎','title':'Global export','text':'Delivering to worldwide markets'},{'icon':'▤','title':'Full documentation','text':'Specs and export files on hand'},{'icon':'✉','title':'Responsive service','text':'Replies within one business day'}]}},
|
||||
'applications_band':{'name':'应用展示带','icon':'⊞','fields':['title','subtitle','items'],'defaults':{'title':'Built for real-world projects','subtitle':'APPLICATIONS','items':[{'icon':'◉','title':'Water supply','text':'Municipal piping and treatment networks.'},{'icon':'◍','title':'Drainage','text':'Gravity and pressure sewer systems.'},{'icon':'✦','title':'Gas','text':'PE pipelines for fuel gas distribution.'},{'icon':'◆','title':'Mining','text':'Abrasion-resistant slurry and vent lines.'}]}},
|
||||
}
|
||||
@@ -416,6 +417,24 @@ def render_blocks(blocks, site, page, entries):
|
||||
parts.append(start+f'<div class="sf-section-head"><h2>{title}</h2></div><address class="sf-map-address">{addr}</address>{action}'+end)
|
||||
elif typ=='form_link':
|
||||
parts.append(start+'<div class="sf-cta-wrap"><div><h2>'+title+'</h2><p>'+desc+'</p></div><a class="sf-button" href="'+safe_href(resolve('href','/contact/'))+'">'+escape(resolve('button','提交询盘'))+' →</a></div>'+end)
|
||||
elif typ=='form':
|
||||
btn=escape(resolve('button_text','Contact Us'));href=safe_href(resolve('button_href','/contact-us/'))
|
||||
form_endpoint=site.get('settings',{}).get('form_endpoint','')
|
||||
if form_endpoint and str(form_endpoint).startswith('https://'):
|
||||
form_html=(
|
||||
f'<div class="sf-form-card"><h2 class="sf-form-title">{title}</h2><p class="sf-form-text">{desc}</p>'
|
||||
f'<form class="sf-form-grid" action="{escape(str(form_endpoint),quote=True)}" method="POST">'
|
||||
f'<div class="sf-form-field"><label>Your Name *</label><input name="name" required maxlength="200" autocomplete="name"></div>'
|
||||
f'<div class="sf-form-field"><label>Email *</label><input name="email" type="email" required maxlength="200" autocomplete="email"></div>'
|
||||
f'<div class="sf-form-field"><label>Phone / WhatsApp</label><input name="phone" maxlength="50" autocomplete="tel"></div>'
|
||||
f'<div class="sf-form-field sf-form-full"><label>Message *</label><textarea name="message" required maxlength="5000" rows="4"></textarea></div>'
|
||||
f'<input name="website" tabindex="-1" autocomplete="off" class="sf-honeypot" aria-hidden="true" style="position:absolute;left:-9999px">'
|
||||
f'<button class="sf-button sf-form-submit" type="submit">Send Inquiry →</button></form></div>')
|
||||
else:
|
||||
form_html=(f'<div class="sf-form-card sf-form-fallback"><h2 class="sf-form-title">{title}</h2><p class="sf-form-text">{desc}</p>'
|
||||
f'<p class="sf-form-note">Configure an external form endpoint in site settings to enable this form.</p>'
|
||||
f'<a class="sf-button" href="{href}">{btn} →</a></div>')
|
||||
parts.append(start+form_html+end)
|
||||
elif typ=='layout':
|
||||
columns=block['columns'];gap=block.get('gap',24)
|
||||
weights=' '.join(f'{col["width"]}fr' for col in columns)
|
||||
|
||||
@@ -97,3 +97,19 @@
|
||||
.sf-section .sf-kicker,.sf-section .sf-feature>span,.sf-section .sf-item-copy small{color:var(--sf-accent-c,var(--accent,#3569d3))!important}
|
||||
.sf-section .sf-button{background:var(--sf-btn-c,var(--accent,#315ee2))!important}
|
||||
.sf-section .sf-link,.sf-section .sf-section-head>a{color:var(--sf-accent-c,var(--accent,#3569d3))!important}
|
||||
|
||||
/* ── 询盘表单区块 ── */
|
||||
.sf-theme-trade-pro .sf-form-card{background:var(--sf-tp-color-surface-muted,#f5f7fa);padding:calc(var(--sf-tp-space-8,32px) + 4px);border-radius:12px;max-width:640px;margin:0 auto}
|
||||
.sf-theme-trade-pro .sf-form-title{font-size:calc(var(--sf-title-size,24px) * .8);color:var(--sf-tp-color-text-primary,#1a2332);margin:0 0 8px}
|
||||
.sf-theme-trade-pro .sf-form-text{color:var(--sf-tp-color-text-muted,#5a6a7e);margin:0 0 24px}
|
||||
.sf-theme-trade-pro .sf-form-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}
|
||||
.sf-theme-trade-pro .sf-form-field{display:flex;flex-direction:column;gap:6px}
|
||||
.sf-theme-trade-pro .sf-form-field label{font-size:12px;font-weight:650;color:var(--sf-tp-color-text-primary,#3d5067)}
|
||||
.sf-theme-trade-pro .sf-form-field input,.sf-theme-trade-pro .sf-form-field textarea{padding:12px 14px;border:1px solid #d9e1ed;border-radius:8px;font:inherit;background:#fff;transition:border-color .15s,box-shadow .15s}
|
||||
.sf-theme-trade-trade-pro .sf-form-field input:focus,.sf-theme-trade-pro .sf-form-field textarea:focus{border-color:var(--sf-tp-color-border-brand,#0874df);box-shadow:0 0 0 3px rgba(8,116,223,.12);outline:none}
|
||||
.sf-theme-trade-pro .sf-form-full{grid-column:1 / -1}
|
||||
.sf-theme-trade-pro .sf-form-submit{grid-column:1 / -1;justify-self:start;margin-top:8px}
|
||||
.sf-theme-trade-pro .sf-form-fallback{text-align:center;padding:48px 32px}
|
||||
.sf-theme-trade-pro .sf-form-note{color:var(--sf-tp-color-text-muted,#8494a6);font-size:13px;margin:0 0 20px}
|
||||
.sf-theme-trade-pro .sf-honeypot{position:absolute!important;left:-9999px!important;width:1px!important;height:1px!important;opacity:0!important;pointer-events:none!important}
|
||||
@media (max-width:620px){.sf-theme-trade-pro .sf-form-grid{grid-template-columns:1fr}}
|
||||
|
||||
Reference in New Issue
Block a user