添加模板分组显示逻辑

This commit is contained in:
puke
2025-11-03 11:45:20 +08:00
parent 20e210b88d
commit 77552c9e80
4 changed files with 85 additions and 27 deletions

View File

@@ -262,6 +262,42 @@ def get_all_templates_with_info() -> List[TemplateInfo]:
return result
def get_templates_grouped_by_size() -> dict:
"""
Get templates grouped by size
Returns:
Dict with size as key, list of TemplateInfo as value
Ordered by orientation priority: portrait > landscape > square
Example:
>>> grouped = get_templates_grouped_by_size()
>>> for size, templates in grouped.items():
... print(f"Size: {size}")
... for t in templates:
... print(f" - {t.display_info.name}")
"""
from collections import defaultdict
templates = get_all_templates_with_info()
grouped = defaultdict(list)
for t in templates:
grouped[t.display_info.size].append(t)
# Sort groups by orientation priority: portrait > landscape > square
orientation_priority = {'portrait': 0, 'landscape': 1, 'square': 2}
sorted_grouped = {}
for size in sorted(grouped.keys(), key=lambda s: (
orientation_priority.get(grouped[s][0].display_info.orientation, 3),
s
)):
sorted_grouped[size] = sorted(grouped[size], key=lambda t: t.display_info.name)
return sorted_grouped
def resolve_template_path(template_input: Optional[str]) -> str:
"""
Resolve template input to full path with validation

View File

@@ -667,52 +667,72 @@ def main():
st.markdown(tr("template.how"))
# Import template utilities
from pixelle_video.utils.template_util import get_all_templates_with_info
from pixelle_video.utils.template_util import get_templates_grouped_by_size
# Get all templates with their info
all_templates = get_all_templates_with_info()
# Get templates grouped by size
grouped_templates = get_templates_grouped_by_size()
if not all_templates:
if not grouped_templates:
st.error("No templates found. Please ensure templates are in templates/ directory with proper structure (e.g., templates/1080x1920/default.html).")
st.stop()
# Build display names with i18n
# Build display options with group separators
ORIENTATION_I18N = {
'portrait': tr('orientation.portrait'),
'landscape': tr('orientation.landscape'),
'square': tr('orientation.square')
}
display_options = {}
for item in all_templates:
info = item.display_info
name = info.name
orientation = ORIENTATION_I18N.get(info.orientation, info.orientation)
# Always show dimensions for standardization
display_name = f"{name} - {orientation}{info.width}×{info.height}"
display_options[display_name] = item.template_path
# Default to "default" portrait if exists
display_names = list(display_options.keys())
display_options = []
template_path_map = {}
default_index = 0
for idx, name in enumerate(display_names):
if "default" in name.lower() and tr('orientation.portrait') in name:
default_index = idx
break
current_index = 0
# Single dropdown with formatted names
for size, templates in grouped_templates.items():
if not templates:
continue
# Get orientation from first template in group
orientation = ORIENTATION_I18N.get(
templates[0].display_info.orientation,
templates[0].display_info.orientation
)
width = templates[0].display_info.width
height = templates[0].display_info.height
# Add group separator
separator = f"─── {orientation} {width}×{height} ───"
display_options.append(separator)
current_index += 1
# Add templates in this group
for t in templates:
display_name = f" {t.display_info.name}"
display_options.append(display_name)
template_path_map[display_name] = t.template_path
# Set default to first "default.html" in portrait orientation
if default_index == 0 and "default.html" in t.display_info.name and t.display_info.orientation == 'portrait':
default_index = current_index
current_index += 1
# Dropdown with grouped display
selected_display_name = st.selectbox(
tr("template.select"),
display_names,
display_options,
index=default_index,
label_visibility="collapsed",
help=tr("template.select_help")
)
# Check if separator is selected (shouldn't happen, but handle it)
if selected_display_name.startswith("───"):
st.warning(tr("template.separator_selected"))
st.stop()
# Get full template path
frame_template = display_options[selected_display_name]
frame_template = template_path_map.get(selected_display_name)
# Template preview expander
with st.expander(tr("template.preview_title"), expanded=False):

View File

@@ -68,11 +68,12 @@
"template.selector": "Template Selection",
"template.select": "Select Template",
"template.select_help": "Select template and video size",
"template.separator_selected": "Please select a specific template, not the group header",
"template.default": "Default",
"template.modern": "Modern",
"template.neon": "Neon",
"template.what": "Controls the visual layout and design style of each frame (title, text, image arrangement)",
"template.how": "Place .html template files in the templates/ folder for automatic detection. Supports custom CSS styles",
"template.how": "Place .html template files in templates/SIZE/ directories (e.g., templates/1080x1920/). Templates are automatically grouped by size. Custom CSS styles are supported",
"template.size_info": "Template Size",
"orientation.portrait": "Portrait",

View File

@@ -68,11 +68,12 @@
"template.selector": "模板选择",
"template.select": "选择模板",
"template.select_help": "选择模板和视频尺寸",
"template.separator_selected": "请选择具体的模板,而不是分组标题",
"template.default": "默认",
"template.modern": "现代",
"template.neon": "霓虹",
"template.what": "控制视频每一帧的视觉布局和设计风格(标题、文本、图片的排版样式)",
"template.how": "将 .html 模板文件放入 templates/ 文件夹即可自动识别。支持自定义 CSS 样式",
"template.how": "将 .html 模板文件放入 templates/尺寸/ 目录(如 templates/1080x1920/),系统会自动按尺寸分组。支持自定义 CSS 样式",
"template.size_info": "模板尺寸",
"orientation.portrait": "竖屏",