diff --git a/app/blueprints.py b/app/blueprints.py index 79d085f..0d10bb4 100644 --- a/app/blueprints.py +++ b/app/blueprints.py @@ -148,12 +148,15 @@ def validate_blocks(blocks): if not isinstance(style,dict):raise ValueError('样式必须为对象') normalized['style']={} for key,val in style.items(): - if key in ('background','text_color'): + if key in ('background','text_color','accent_color','button_color'): if not isinstance(val,str) or not re.fullmatch(r'#[0-9a-fA-F]{6}',val):raise ValueError('颜色必须为六位十六进制') normalized['style'][key]=val elif key in ('padding','tablet_padding','mobile_padding'): if type(val) is not int or not 0<=val<=120:raise ValueError('区块间距必须是0-120整数') normalized['style'][key]=val + elif key in ('title_size','text_size'): + if type(val) is not int or not 10<=val<=80:raise ValueError('字号必须是10-80整数') + normalized['style'][key]=val elif key in ('hide_mobile','hide_tablet'): if type(val) is not bool:raise ValueError('设备显隐必须是布尔值') normalized['style'][key]=val @@ -267,12 +270,16 @@ def render_blocks(blocks, site, page, entries): typ=block['type']; resolve=lambda key,default='':resolve_text(block.get(key,default),site,page) title=escape(resolve('title')); subtitle=escape(resolve('subtitle'));desc=escape(resolve('description')) raw_style=block.get('style') or {}; s=[] - for key,var in [('background','--sf-bg'),('text_color','--sf-fg')]: + for key,var in [('background','--sf-bg'),('text_color','--sf-fg'),('accent_color','--sf-accent-c'),('button_color','--sf-btn-c')]: val=str(raw_style.get(key,'')).strip() if re.fullmatch(r'#[a-fA-F0-9]{6}',val):s.append(f'{var}:{val}') if 'padding' in raw_style: try:pad=max(0,min(120,int(raw_style['padding'])));s.append(f'--sf-pad:{pad}px') except (ValueError,TypeError):pass + for key,var,lo,hi in [('title_size','--sf-title-size',10,80),('text_size','--sf-text-size',10,24)]: + if key in raw_style: + try:size=max(lo,min(hi,int(raw_style[key])));s.append(f'{var}:{size}px') + except (ValueError,TypeError):pass style=' style="'+escape(';'.join(s),quote=True)+'"' if s else '' start=f'
' end='
' diff --git a/app/static/blocks.css b/app/static/blocks.css index a2e9f92..4789dd1 100644 --- a/app/static/blocks.css +++ b/app/static/blocks.css @@ -89,3 +89,11 @@ .sf-app-tile h3{font-size:20px;margin:0 0 6px} .sf-app-tile p{font-size:14px;line-height:1.65;opacity:.75;margin:0} @media(max-width:540px){.sf-applications-band{grid-template-columns:minmax(0,1fr)}} + +/* ── 区块级字号/颜色自定义(CSS 变量消费)── */ +.sf-section h1,.sf-section h2{font-size:var(--sf-title-size,clamp(38px,5vw,76px))!important} +.sf-section h3{font-size:var(--sf-title-size,clamp(22px,2vw,28px))!important} +.sf-section p,.sf-section li,.sf-section .sf-prose{font-size:var(--sf-text-size,16px)!important} +.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} diff --git a/app/static/editor.js b/app/static/editor.js index df15bd4..e7e4f63 100644 --- a/app/static/editor.js +++ b/app/static/editor.js @@ -407,7 +407,7 @@ const Studio={ out+=''; } out+=`
响应式样式
`; - out+=`
快速设置外观

不必先调色值:选择样式后会立即更新预览,也可以撤销。

自定义外观
`; + out+=`
快速设置外观

不必先调色值:选择样式后会立即更新预览,也可以撤销。

字体与颜色
背景与间距
`; const sharing=selectedChildId?editorTools.findChildInRoot(blocks,b.id,selectedChildId)?.child?.shared_ref:b.shared_ref; if(sharing)out+=`
已关联公共组件 · v${html(sharing.version)}

此区块将来可以按需同步新版。直接修改后会被视为本地定制。

`; out+='
';