182 lines
5.8 KiB
Python
182 lines
5.8 KiB
Python
"""
|
|
前端组件模块
|
|
提供可重用的UI组件和交互逻辑
|
|
"""
|
|
|
|
class UIComponent:
|
|
"""UI组件基类"""
|
|
|
|
def __init__(self, element_id: str):
|
|
self.element_id = element_id
|
|
|
|
def render(self) -> str:
|
|
"""渲染组件"""
|
|
raise NotImplementedError
|
|
|
|
def get_script(self) -> str:
|
|
"""获取组件相关的JavaScript代码"""
|
|
return ""
|
|
|
|
class ProgressBar(UIComponent):
|
|
"""进度条组件"""
|
|
|
|
def __init__(self, element_id: str, label: str = "进度"):
|
|
super().__init__(element_id)
|
|
self.label = label
|
|
|
|
def render(self) -> str:
|
|
return f"""
|
|
<div class="form-group">
|
|
<label>{self.label}:</label>
|
|
<div class="progress" id="{self.element_id}_container" style="display: none;">
|
|
<div class="progress-bar" id="{self.element_id}" style="width: 0%">0%</div>
|
|
</div>
|
|
</div>
|
|
"""
|
|
|
|
def get_script(self) -> str:
|
|
return f"""
|
|
function showProgress_{self.element_id}(percent) {{
|
|
const container = document.getElementById('{self.element_id}_container');
|
|
const bar = document.getElementById('{self.element_id}');
|
|
container.style.display = 'block';
|
|
bar.style.width = percent + '%';
|
|
bar.textContent = percent + '%';
|
|
}}
|
|
|
|
function hideProgress_{self.element_id}() {{
|
|
const container = document.getElementById('{self.element_id}_container');
|
|
container.style.display = 'none';
|
|
}}
|
|
"""
|
|
|
|
class AlertBox(UIComponent):
|
|
"""提示框组件"""
|
|
|
|
def __init__(self, element_id: str):
|
|
super().__init__(element_id)
|
|
|
|
def render(self) -> str:
|
|
return f"""
|
|
<div id="{self.element_id}" class="alert hidden"></div>
|
|
"""
|
|
|
|
def get_script(self) -> str:
|
|
return f"""
|
|
function showAlert_{self.element_id}(message, type = 'info') {{
|
|
const alertBox = document.getElementById('{self.element_id}');
|
|
alertBox.textContent = message;
|
|
alertBox.className = 'alert ' + type;
|
|
alertBox.classList.remove('hidden');
|
|
|
|
// 3秒后自动隐藏
|
|
setTimeout(() => {{
|
|
alertBox.classList.add('hidden');
|
|
}}, 3000);
|
|
}}
|
|
"""
|
|
|
|
class Modal(UIComponent):
|
|
"""模态框组件"""
|
|
|
|
def __init__(self, element_id: str, title: str):
|
|
super().__init__(element_id)
|
|
self.title = title
|
|
|
|
def render(self) -> str:
|
|
return f"""
|
|
<div id="{self.element_id}" class="modal hidden">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3>{self.title}</h3>
|
|
<span class="close" onclick="closeModal_{self.element_id}()">×</span>
|
|
</div>
|
|
<div class="modal-body" id="{self.element_id}_body">
|
|
<!-- 模态框内容 -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
"""
|
|
|
|
def get_script(self) -> str:
|
|
return f"""
|
|
function showModal_{self.element_id}(content = '') {{
|
|
const modal = document.getElementById('{self.element_id}');
|
|
const body = document.getElementById('{self.element_id}_body');
|
|
if (content) {{
|
|
body.innerHTML = content;
|
|
}}
|
|
modal.classList.remove('hidden');
|
|
document.body.style.overflow = 'hidden';
|
|
}}
|
|
|
|
function closeModal_{self.element_id}() {{
|
|
const modal = document.getElementById('{self.element_id}');
|
|
modal.classList.add('hidden');
|
|
document.body.style.overflow = 'auto';
|
|
}}
|
|
|
|
// 点击模态框外部关闭
|
|
document.getElementById('{self.element_id}').addEventListener('click', function(e) {{
|
|
if (e.target === this) {{
|
|
closeModal_{self.element_id}();
|
|
}}
|
|
}});
|
|
"""
|
|
|
|
class Tabs(UIComponent):
|
|
"""标签页组件"""
|
|
|
|
def __init__(self, element_id: str, tabs: list):
|
|
super().__init__(element_id)
|
|
self.tabs = tabs # [(tab_id, tab_label), ...]
|
|
|
|
def render(self) -> str:
|
|
tab_buttons = ""
|
|
tab_contents = ""
|
|
|
|
for i, (tab_id, tab_label) in enumerate(self.tabs):
|
|
active_class = "active" if i == 0 else ""
|
|
tab_buttons += f"""
|
|
<button class="tab-button {active_class}" onclick="switchTab_{self.element_id}('{tab_id}')">{tab_label}</button>
|
|
"""
|
|
|
|
tab_contents += f"""
|
|
<div id="{tab_id}" class="tab-content {'active' if i == 0 else ''}">
|
|
<!-- {tab_label} 内容 -->
|
|
</div>
|
|
"""
|
|
|
|
return f"""
|
|
<div class="tabs">
|
|
<div class="tab-buttons">
|
|
{tab_buttons}
|
|
</div>
|
|
<div class="tab-contents">
|
|
{tab_contents}
|
|
</div>
|
|
</div>
|
|
"""
|
|
|
|
def get_script(self) -> str:
|
|
return f"""
|
|
function switchTab_{self.element_id}(tabId) {{
|
|
// 隐藏所有标签内容
|
|
const tabContents = document.querySelectorAll('.tab-content');
|
|
tabContents.forEach(content => {{
|
|
content.classList.remove('active');
|
|
}});
|
|
|
|
// 移除所有按钮的激活状态
|
|
const tabButtons = document.querySelectorAll('.tab-button');
|
|
tabButtons.forEach(button => {{
|
|
button.classList.remove('active');
|
|
}});
|
|
|
|
// 显示选中的标签内容
|
|
document.getElementById(tabId).classList.add('active');
|
|
|
|
// 激活选中的按钮
|
|
event.target.classList.add('active');
|
|
}}
|
|
""" |