添加模板分组显示逻辑
This commit is contained in:
@@ -262,6 +262,42 @@ def get_all_templates_with_info() -> List[TemplateInfo]:
|
|||||||
return result
|
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:
|
def resolve_template_path(template_input: Optional[str]) -> str:
|
||||||
"""
|
"""
|
||||||
Resolve template input to full path with validation
|
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"))
|
st.markdown(tr("template.how"))
|
||||||
|
|
||||||
# Import template utilities
|
# 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
|
# Get templates grouped by size
|
||||||
all_templates = get_all_templates_with_info()
|
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.error("No templates found. Please ensure templates are in templates/ directory with proper structure (e.g., templates/1080x1920/default.html).")
|
||||||
st.stop()
|
st.stop()
|
||||||
|
|
||||||
# Build display names with i18n
|
# Build display options with group separators
|
||||||
ORIENTATION_I18N = {
|
ORIENTATION_I18N = {
|
||||||
'portrait': tr('orientation.portrait'),
|
'portrait': tr('orientation.portrait'),
|
||||||
'landscape': tr('orientation.landscape'),
|
'landscape': tr('orientation.landscape'),
|
||||||
'square': tr('orientation.square')
|
'square': tr('orientation.square')
|
||||||
}
|
}
|
||||||
|
|
||||||
display_options = {}
|
display_options = []
|
||||||
for item in all_templates:
|
template_path_map = {}
|
||||||
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())
|
|
||||||
default_index = 0
|
default_index = 0
|
||||||
for idx, name in enumerate(display_names):
|
current_index = 0
|
||||||
if "default" in name.lower() and tr('orientation.portrait') in name:
|
|
||||||
default_index = idx
|
|
||||||
break
|
|
||||||
|
|
||||||
# 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(
|
selected_display_name = st.selectbox(
|
||||||
tr("template.select"),
|
tr("template.select"),
|
||||||
display_names,
|
display_options,
|
||||||
index=default_index,
|
index=default_index,
|
||||||
label_visibility="collapsed",
|
label_visibility="collapsed",
|
||||||
help=tr("template.select_help")
|
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
|
# Get full template path
|
||||||
frame_template = display_options[selected_display_name]
|
frame_template = template_path_map.get(selected_display_name)
|
||||||
|
|
||||||
# Template preview expander
|
# Template preview expander
|
||||||
with st.expander(tr("template.preview_title"), expanded=False):
|
with st.expander(tr("template.preview_title"), expanded=False):
|
||||||
|
|||||||
@@ -68,11 +68,12 @@
|
|||||||
"template.selector": "Template Selection",
|
"template.selector": "Template Selection",
|
||||||
"template.select": "Select Template",
|
"template.select": "Select Template",
|
||||||
"template.select_help": "Select template and video size",
|
"template.select_help": "Select template and video size",
|
||||||
|
"template.separator_selected": "Please select a specific template, not the group header",
|
||||||
"template.default": "Default",
|
"template.default": "Default",
|
||||||
"template.modern": "Modern",
|
"template.modern": "Modern",
|
||||||
"template.neon": "Neon",
|
"template.neon": "Neon",
|
||||||
"template.what": "Controls the visual layout and design style of each frame (title, text, image arrangement)",
|
"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",
|
"template.size_info": "Template Size",
|
||||||
|
|
||||||
"orientation.portrait": "Portrait",
|
"orientation.portrait": "Portrait",
|
||||||
|
|||||||
@@ -68,11 +68,12 @@
|
|||||||
"template.selector": "模板选择",
|
"template.selector": "模板选择",
|
||||||
"template.select": "选择模板",
|
"template.select": "选择模板",
|
||||||
"template.select_help": "选择模板和视频尺寸",
|
"template.select_help": "选择模板和视频尺寸",
|
||||||
|
"template.separator_selected": "请选择具体的模板,而不是分组标题",
|
||||||
"template.default": "默认",
|
"template.default": "默认",
|
||||||
"template.modern": "现代",
|
"template.modern": "现代",
|
||||||
"template.neon": "霓虹",
|
"template.neon": "霓虹",
|
||||||
"template.what": "控制视频每一帧的视觉布局和设计风格(标题、文本、图片的排版样式)",
|
"template.what": "控制视频每一帧的视觉布局和设计风格(标题、文本、图片的排版样式)",
|
||||||
"template.how": "将 .html 模板文件放入 templates/ 文件夹即可自动识别。支持自定义 CSS 样式",
|
"template.how": "将 .html 模板文件放入 templates/尺寸/ 目录(如 templates/1080x1920/),系统会自动按尺寸分组。支持自定义 CSS 样式",
|
||||||
"template.size_info": "模板尺寸",
|
"template.size_info": "模板尺寸",
|
||||||
|
|
||||||
"orientation.portrait": "竖屏",
|
"orientation.portrait": "竖屏",
|
||||||
|
|||||||
Reference in New Issue
Block a user