添加模板分组显示逻辑
This commit is contained in:
@@ -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
|
||||
|
||||
70
web/app.py
70
web/app.py
@@ -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):
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "竖屏",
|
||||
|
||||
Reference in New Issue
Block a user