页面优化
This commit is contained in:
@@ -11,9 +11,68 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container mt-4">
|
||||
<div class="row">
|
||||
<div class="col-md-8 offset-md-2">
|
||||
<div class="main-layout">
|
||||
<!-- 侧边栏切换按钮 -->
|
||||
<button class="sidebar-toggle" id="sidebarToggle">
|
||||
<i class="fas fa-filter"></i>
|
||||
<span>筛选</span>
|
||||
</button>
|
||||
|
||||
<!-- 侧边栏 -->
|
||||
<div class="sidebar" id="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<h3>选择场景</h3>
|
||||
<button class="sidebar-close" id="sidebarClose">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 筛选控制 -->
|
||||
<div class="sidebar-filters">
|
||||
<div class="filter-group">
|
||||
<label for="industryFilter">行业</label>
|
||||
<select id="industryFilter" class="custom-select">
|
||||
<option value="all">全部行业</option>
|
||||
{% for industry in industries %}
|
||||
<option value="{{ industry }}">{{ industry }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="filter-group">
|
||||
<label for="professionFilter">职业</label>
|
||||
<select id="professionFilter" class="custom-select">
|
||||
<option value="all">全部职业</option>
|
||||
{% for profession in professions %}
|
||||
<option value="{{ profession }}">{{ profession }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="filter-group">
|
||||
<label for="subCategoryFilter">领域</label>
|
||||
<select id="subCategoryFilter" class="custom-select">
|
||||
<option value="all">全部领域</option>
|
||||
{% for sub_category in sub_categories %}
|
||||
<option value="{{ sub_category }}">{{ sub_category }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 场景分类 -->
|
||||
<div class="sidebar-categories">
|
||||
<div class="category-tabs">
|
||||
<div class="tab active" data-category="all">全部</div>
|
||||
{% for category in categories %}
|
||||
<div class="tab" data-category="{{ category }}">{{ category }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 主内容区域 -->
|
||||
<div class="main-content">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2>提示词生成器</h2>
|
||||
<a href="{{ url_for('main.expert_generate') }}" class="btn btn-primary">
|
||||
@@ -37,36 +96,6 @@
|
||||
</div>
|
||||
|
||||
<div class="templates-section">
|
||||
<div class="section-header">
|
||||
<h2>选择场景</h2>
|
||||
<div class="filter-controls">
|
||||
<select id="industryFilter" class="custom-select">
|
||||
<option value="all">全部行业</option>
|
||||
{% for industry in industries %}
|
||||
<option value="{{ industry }}">{{ industry }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<select id="professionFilter" class="custom-select">
|
||||
<option value="all">全部职业</option>
|
||||
{% for profession in professions %}
|
||||
<option value="{{ profession }}">{{ profession }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<select id="subCategoryFilter" class="custom-select">
|
||||
<option value="all">全部领域</option>
|
||||
{% for sub_category in sub_categories %}
|
||||
<option value="{{ sub_category }}">{{ sub_category }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category-tabs">
|
||||
<div class="tab active" data-category="all">全部</div>
|
||||
{% for category in categories %}
|
||||
<div class="tab" data-category="{{ category }}">{{ category }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="template-grid">
|
||||
{% for template in templates %}
|
||||
@@ -189,14 +218,89 @@
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--primary-color: #4a90e2;
|
||||
--primary-dark: #357abd;
|
||||
--secondary-color: #f5f7fa;
|
||||
--text-color: #2c3e50;
|
||||
--border-color: #e0e0e0;
|
||||
--hover-color: #e8f0fe;
|
||||
--success-color: #4CAF50;
|
||||
--success-dark: #45a049;
|
||||
/* 间距系统 - 基于4px基准 */
|
||||
--spacing-unit: 0.25rem; /* 4px基准 */
|
||||
--spacing-xs: calc(var(--spacing-unit) * 1); /* 4px */
|
||||
--spacing-sm: calc(var(--spacing-unit) * 2); /* 8px */
|
||||
--spacing-md: calc(var(--spacing-unit) * 4); /* 16px */
|
||||
--spacing-lg: calc(var(--spacing-unit) * 6); /* 24px */
|
||||
--spacing-xl: calc(var(--spacing-unit) * 8); /* 32px */
|
||||
--spacing-2xl: calc(var(--spacing-unit) * 12); /* 48px */
|
||||
--spacing-3xl: calc(var(--spacing-unit) * 16); /* 64px */
|
||||
|
||||
/* 容器与布局 */
|
||||
--container-max-width: 1400px;
|
||||
--section-padding: clamp(2rem, 5vw, 4rem);
|
||||
--border-radius: 12px;
|
||||
--border-radius-sm: 8px;
|
||||
--border-radius-lg: 16px;
|
||||
|
||||
/* 色彩系统 - 层级化设计 */
|
||||
--color-primary: #2563eb;
|
||||
--color-primary-light: #3b82f6;
|
||||
--color-primary-dark: #1d4ed8;
|
||||
--color-secondary: #64748b;
|
||||
--color-secondary-light: #94a3b8;
|
||||
--color-secondary-dark: #475569;
|
||||
--color-success: #10b981;
|
||||
--color-warning: #f59e0b;
|
||||
--color-error: #ef4444;
|
||||
--color-info: #06b6d4;
|
||||
|
||||
/* 中性色系 */
|
||||
--color-white: #ffffff;
|
||||
--color-gray-50: #f8fafc;
|
||||
--color-gray-100: #f1f5f9;
|
||||
--color-gray-200: #e2e8f0;
|
||||
--color-gray-300: #cbd5e1;
|
||||
--color-gray-400: #94a3b8;
|
||||
--color-gray-500: #64748b;
|
||||
--color-gray-600: #475569;
|
||||
--color-gray-700: #334155;
|
||||
--color-gray-800: #1e293b;
|
||||
--color-gray-900: #0f172a;
|
||||
|
||||
/* 字体系统 */
|
||||
--text-xs: 0.75rem; /* 12px */
|
||||
--text-sm: 0.875rem; /* 14px */
|
||||
--text-base: 1rem; /* 16px */
|
||||
--text-lg: 1.125rem; /* 18px */
|
||||
--text-xl: 1.25rem; /* 20px */
|
||||
--text-2xl: 1.5rem; /* 24px */
|
||||
--text-3xl: 1.875rem; /* 30px */
|
||||
--text-4xl: 2.25rem; /* 36px */
|
||||
|
||||
/* 字重系统 */
|
||||
--font-weight-normal: 400;
|
||||
--font-weight-medium: 500;
|
||||
--font-weight-semibold: 600;
|
||||
--font-weight-bold: 700;
|
||||
|
||||
/* 行高系统 */
|
||||
--line-height-tight: 1.25;
|
||||
--line-height-normal: 1.5;
|
||||
--line-height-relaxed: 1.75;
|
||||
|
||||
/* 阴影系统 */
|
||||
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
||||
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||
|
||||
/* 过渡动画 */
|
||||
--transition-fast: 150ms ease-in-out;
|
||||
--transition-normal: 300ms ease-in-out;
|
||||
--transition-slow: 500ms ease-in-out;
|
||||
|
||||
/* 兼容性变量 */
|
||||
--primary-color: var(--color-primary);
|
||||
--primary-dark: var(--color-primary-dark);
|
||||
--secondary-color: var(--color-gray-100);
|
||||
--text-color: var(--color-gray-800);
|
||||
--border-color: var(--color-gray-200);
|
||||
--hover-color: var(--color-gray-50);
|
||||
--success-color: var(--color-success);
|
||||
--success-dark: #059669;
|
||||
}
|
||||
|
||||
.hero {
|
||||
@@ -238,10 +342,164 @@
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
max-width: 1200px;
|
||||
/* 主布局 */
|
||||
.main-layout {
|
||||
display: flex;
|
||||
max-width: var(--container-max-width);
|
||||
margin: 0 auto;
|
||||
padding: 0 2rem;
|
||||
gap: var(--spacing-xl);
|
||||
padding: 0 var(--spacing-lg);
|
||||
min-height: calc(100vh - 200px);
|
||||
}
|
||||
|
||||
/* 侧边栏切换按钮 */
|
||||
.sidebar-toggle {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: var(--spacing-md);
|
||||
transform: translateY(-50%);
|
||||
background: var(--primary-color);
|
||||
color: var(--color-white);
|
||||
border: none;
|
||||
border-radius: var(--border-radius);
|
||||
padding: var(--spacing-md);
|
||||
cursor: pointer;
|
||||
box-shadow: var(--shadow-lg);
|
||||
z-index: 1000;
|
||||
transition: var(--transition-normal);
|
||||
}
|
||||
|
||||
.sidebar-toggle:hover {
|
||||
background: var(--color-primary-dark);
|
||||
transform: translateY(-50%) scale(1.05);
|
||||
}
|
||||
|
||||
.sidebar-toggle i {
|
||||
margin-right: var(--spacing-xs);
|
||||
}
|
||||
|
||||
/* 侧边栏 */
|
||||
.sidebar {
|
||||
width: 280px;
|
||||
background: var(--color-white);
|
||||
border-radius: var(--border-radius);
|
||||
box-shadow: var(--shadow-md);
|
||||
padding: var(--spacing-lg);
|
||||
height: fit-content;
|
||||
position: sticky;
|
||||
top: var(--spacing-lg);
|
||||
transition: var(--transition-normal);
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: var(--spacing-lg);
|
||||
padding-bottom: var(--spacing-md);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.sidebar-header h3 {
|
||||
margin: 0;
|
||||
font-size: var(--text-lg);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.sidebar-close {
|
||||
display: none;
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--color-gray-500);
|
||||
cursor: pointer;
|
||||
padding: var(--spacing-xs);
|
||||
border-radius: var(--border-radius-sm);
|
||||
transition: var(--transition-fast);
|
||||
}
|
||||
|
||||
.sidebar-close:hover {
|
||||
background: var(--color-gray-100);
|
||||
color: var(--color-gray-700);
|
||||
}
|
||||
|
||||
/* 侧边栏筛选 */
|
||||
.sidebar-filters {
|
||||
margin-bottom: var(--spacing-lg);
|
||||
}
|
||||
|
||||
.sidebar-filters .filter-group {
|
||||
margin-bottom: var(--spacing-md);
|
||||
}
|
||||
|
||||
.sidebar-filters label {
|
||||
display: block;
|
||||
margin-bottom: var(--spacing-xs);
|
||||
font-size: var(--text-sm);
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--color-gray-700);
|
||||
}
|
||||
|
||||
.sidebar-filters .custom-select {
|
||||
width: 100%;
|
||||
padding: var(--spacing-sm) var(--spacing-md);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--border-radius-sm);
|
||||
font-size: var(--text-sm);
|
||||
background: var(--color-white);
|
||||
transition: var(--transition-fast);
|
||||
}
|
||||
|
||||
.sidebar-filters .custom-select:focus {
|
||||
outline: none;
|
||||
border-color: var(--primary-color);
|
||||
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
|
||||
}
|
||||
|
||||
/* 侧边栏分类 */
|
||||
.sidebar-categories {
|
||||
margin-top: var(--spacing-lg);
|
||||
}
|
||||
|
||||
.sidebar-categories .category-tabs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.sidebar-categories .tab {
|
||||
padding: var(--spacing-sm) var(--spacing-md);
|
||||
background: var(--color-gray-50);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--border-radius-sm);
|
||||
cursor: pointer;
|
||||
transition: var(--transition-fast);
|
||||
font-size: var(--text-sm);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.sidebar-categories .tab:hover {
|
||||
background: var(--color-gray-100);
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.sidebar-categories .tab.active {
|
||||
background: var(--primary-color);
|
||||
color: var(--color-white);
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
/* 主内容区域 */
|
||||
.main-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
max-width: var(--container-max-width);
|
||||
margin: 0 auto;
|
||||
padding: 0 var(--spacing-lg);
|
||||
}
|
||||
|
||||
.section-header {
|
||||
@@ -293,30 +551,34 @@
|
||||
|
||||
.template-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 2rem;
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
gap: var(--spacing-md);
|
||||
margin-bottom: var(--spacing-2xl);
|
||||
padding: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.template-card {
|
||||
position: relative;
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
min-height: 160px;
|
||||
}
|
||||
|
||||
.template-content {
|
||||
display: flex;
|
||||
padding: 1.5rem;
|
||||
background: white;
|
||||
padding: var(--spacing-md);
|
||||
background: var(--color-white);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 12px;
|
||||
border-radius: var(--border-radius);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
transition: var(--transition-normal);
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.template-content:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||
box-shadow: var(--shadow-lg);
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
@@ -338,16 +600,18 @@
|
||||
}
|
||||
|
||||
.template-info h3 {
|
||||
margin: 0 0 0.5rem;
|
||||
font-size: 1.1rem;
|
||||
margin: 0 0 var(--spacing-sm);
|
||||
font-size: var(--text-sm);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
color: var(--text-color);
|
||||
line-height: var(--line-height-tight);
|
||||
}
|
||||
|
||||
.template-info p {
|
||||
margin: 0 0 1rem;
|
||||
font-size: 0.9rem;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
margin: 0 0 var(--spacing-sm);
|
||||
font-size: var(--text-xs);
|
||||
color: var(--color-gray-600);
|
||||
line-height: var(--line-height-normal);
|
||||
}
|
||||
|
||||
.template-header {
|
||||
@@ -496,31 +760,31 @@
|
||||
.template-categories {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
padding: 8px;
|
||||
background: #f8f9fa;
|
||||
border-radius: 6px;
|
||||
gap: var(--spacing-xs);
|
||||
margin-bottom: var(--spacing-sm);
|
||||
padding: var(--spacing-xs);
|
||||
background: var(--color-gray-50);
|
||||
border-radius: var(--border-radius-sm);
|
||||
}
|
||||
|
||||
.category-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 4px 8px;
|
||||
background: white;
|
||||
border-radius: 4px;
|
||||
font-size: 0.85rem;
|
||||
gap: var(--spacing-xs);
|
||||
padding: var(--spacing-xs) var(--spacing-sm);
|
||||
background: var(--color-white);
|
||||
border-radius: var(--border-radius-sm);
|
||||
font-size: var(--text-xs);
|
||||
}
|
||||
|
||||
.category-label {
|
||||
color: #666;
|
||||
font-weight: 500;
|
||||
color: var(--color-gray-600);
|
||||
font-weight: var(--font-weight-medium);
|
||||
}
|
||||
|
||||
.category-value {
|
||||
color: var(--primary-color);
|
||||
font-weight: 600;
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
|
||||
.template-card {
|
||||
@@ -567,6 +831,16 @@
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* 快速筛选标签样式 */
|
||||
.quick-filters {
|
||||
display: flex;
|
||||
gap: var(--spacing-md);
|
||||
margin: var(--spacing-lg) 0 var(--spacing-xl) 0;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
padding: 0 var(--spacing-sm);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.hero {
|
||||
padding: 3rem 1rem;
|
||||
@@ -576,12 +850,66 @@
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
padding: 0 1rem;
|
||||
.main-layout {
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-md);
|
||||
padding: 0 var(--spacing-md);
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 280px;
|
||||
height: 100vh;
|
||||
z-index: 1001;
|
||||
transition: left var(--transition-normal);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sidebar.show {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.sidebar-close {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.template-grid {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
||||
gap: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.quick-filters {
|
||||
gap: 6px;
|
||||
margin: 10px 0;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.filter-tab {
|
||||
padding: 6px 12px;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.sidebar-categories .category-tabs {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.sidebar-categories .tab {
|
||||
flex: 1;
|
||||
min-width: 120px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
@@ -697,12 +1025,15 @@
|
||||
}
|
||||
|
||||
.search-section {
|
||||
margin-bottom: 1.5rem;
|
||||
margin-bottom: 1.2rem;
|
||||
max-width: 800px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
position: relative;
|
||||
max-width: 600px;
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@@ -751,10 +1082,12 @@
|
||||
|
||||
.template-actions {
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
top: var(--spacing-sm);
|
||||
right: var(--spacing-sm);
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
display: flex;
|
||||
gap: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.template-card:hover .template-actions {
|
||||
@@ -762,12 +1095,13 @@
|
||||
}
|
||||
|
||||
.btn-delete {
|
||||
padding: 0.5rem;
|
||||
padding: var(--spacing-xs);
|
||||
background: none;
|
||||
border: none;
|
||||
color: #dc3545;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
font-size: var(--text-xs);
|
||||
}
|
||||
|
||||
.btn-delete:hover {
|
||||
@@ -1382,14 +1716,15 @@ style.textContent = `
|
||||
}
|
||||
|
||||
.btn-favorite {
|
||||
padding: 8px 16px;
|
||||
padding: var(--spacing-xs) var(--spacing-sm);
|
||||
background: #ff6b6b;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
border-radius: var(--border-radius-sm);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
margin-left: 8px;
|
||||
margin-left: var(--spacing-sm);
|
||||
font-size: var(--text-xs);
|
||||
}
|
||||
|
||||
.btn-favorite:hover {
|
||||
@@ -1959,6 +2294,9 @@ function initializeAnimations() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// 延迟初始化动画,确保页面完全加载
|
||||
setTimeout(initializeAnimations, 100);
|
||||
|
||||
// 初始化现代交互功能
|
||||
initializeModernInteractions();
|
||||
});
|
||||
|
||||
// 收藏功能
|
||||
@@ -2028,5 +2366,257 @@ function addToFavorites() {
|
||||
alert('收藏失败,请稍后重试');
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 现代交互功能系统 ====================
|
||||
|
||||
// 初始化现代交互功能
|
||||
function initializeModernInteractions() {
|
||||
// 初始化平滑滚动
|
||||
initializeSmoothScroll();
|
||||
|
||||
// 初始化焦点管理
|
||||
initializeFocusManagement();
|
||||
|
||||
// 初始化悬停效果
|
||||
initializeHoverEffects();
|
||||
|
||||
// 初始化键盘导航
|
||||
initializeKeyboardNavigation();
|
||||
|
||||
// 初始化性能优化
|
||||
initializePerformanceOptimizations();
|
||||
|
||||
console.log('现代交互功能初始化完成');
|
||||
}
|
||||
|
||||
// 平滑滚动与焦点管理
|
||||
function initializeSmoothScroll() {
|
||||
// 平滑滚动到目标元素
|
||||
window.smoothScroll = (target) => {
|
||||
if (typeof target === 'string') {
|
||||
target = document.querySelector(target);
|
||||
}
|
||||
if (target) {
|
||||
target.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'nearest'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 为所有内部链接添加平滑滚动
|
||||
document.querySelectorAll('a[href^="#"]').forEach(link => {
|
||||
link.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
const targetId = this.getAttribute('href').substring(1);
|
||||
const target = document.getElementById(targetId);
|
||||
if (target) {
|
||||
smoothScroll(target);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 焦点管理系统
|
||||
function initializeFocusManagement() {
|
||||
// 焦点可见性管理
|
||||
const focusVisibleClass = 'focus-visible';
|
||||
|
||||
// 添加焦点样式
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
.focus-visible {
|
||||
outline: 2px solid var(--color-primary);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.focus-visible:focus {
|
||||
outline: 2px solid var(--color-primary);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
// 键盘焦点管理
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Tab') {
|
||||
document.body.classList.add('keyboard-navigation');
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('mousedown', function() {
|
||||
document.body.classList.remove('keyboard-navigation');
|
||||
});
|
||||
}
|
||||
|
||||
// 悬停效果统一管理
|
||||
function initializeHoverEffects() {
|
||||
// 为模板卡片添加悬停效果
|
||||
document.querySelectorAll('.template-card').forEach(card => {
|
||||
card.style.transition = 'var(--transition-normal)';
|
||||
card.addEventListener('mouseenter', function() {
|
||||
this.style.transform = 'translateY(-2px)';
|
||||
this.style.boxShadow = 'var(--shadow-lg)';
|
||||
});
|
||||
card.addEventListener('mouseleave', function() {
|
||||
this.style.transform = 'translateY(0)';
|
||||
this.style.boxShadow = 'var(--shadow-sm)';
|
||||
});
|
||||
});
|
||||
|
||||
// 为按钮添加悬停效果
|
||||
document.querySelectorAll('button, .btn').forEach(button => {
|
||||
button.style.transition = 'var(--transition-fast)';
|
||||
});
|
||||
}
|
||||
|
||||
// 键盘导航支持
|
||||
function initializeKeyboardNavigation() {
|
||||
// 模板卡片键盘导航
|
||||
document.querySelectorAll('.template-card').forEach((card, index) => {
|
||||
card.setAttribute('tabindex', '0');
|
||||
card.setAttribute('role', 'button');
|
||||
card.setAttribute('aria-label', `选择模板 ${index + 1}`);
|
||||
|
||||
card.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
const radio = this.querySelector('input[type="radio"]');
|
||||
if (radio) {
|
||||
radio.checked = true;
|
||||
radio.dispatchEvent(new Event('change'));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 筛选标签键盘导航
|
||||
document.querySelectorAll('.filter-tab').forEach(tab => {
|
||||
tab.setAttribute('tabindex', '0');
|
||||
tab.setAttribute('role', 'button');
|
||||
|
||||
tab.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
this.click();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 性能优化功能
|
||||
function initializePerformanceOptimizations() {
|
||||
// 图片懒加载
|
||||
if ('IntersectionObserver' in window) {
|
||||
const imageObserver = new IntersectionObserver((entries, observer) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
const img = entry.target;
|
||||
if (img.dataset.src) {
|
||||
img.src = img.dataset.src;
|
||||
img.removeAttribute('data-src');
|
||||
observer.unobserve(img);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('img[data-src]').forEach(img => {
|
||||
imageObserver.observe(img);
|
||||
});
|
||||
}
|
||||
|
||||
// 防抖搜索
|
||||
let searchTimeout;
|
||||
const searchInput = document.getElementById('templateSearch');
|
||||
if (searchInput) {
|
||||
searchInput.addEventListener('input', function() {
|
||||
clearTimeout(searchTimeout);
|
||||
searchTimeout = setTimeout(() => {
|
||||
performSearchAndFilter();
|
||||
}, 300);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 现代CSS类工具函数
|
||||
const modernUtils = {
|
||||
// 添加CSS类
|
||||
addClass: (element, className) => {
|
||||
if (element && element.classList) {
|
||||
element.classList.add(className);
|
||||
}
|
||||
},
|
||||
|
||||
// 移除CSS类
|
||||
removeClass: (element, className) => {
|
||||
if (element && element.classList) {
|
||||
element.classList.remove(className);
|
||||
}
|
||||
},
|
||||
|
||||
// 切换CSS类
|
||||
toggleClass: (element, className) => {
|
||||
if (element && element.classList) {
|
||||
element.classList.toggle(className);
|
||||
}
|
||||
},
|
||||
|
||||
// 检查是否有CSS类
|
||||
hasClass: (element, className) => {
|
||||
return element && element.classList && element.classList.contains(className);
|
||||
}
|
||||
};
|
||||
|
||||
// 导出工具函数到全局
|
||||
window.modernUtils = modernUtils;
|
||||
window.smoothScroll = window.smoothScroll || smoothScroll;
|
||||
|
||||
// ==================== 侧边栏功能 ====================
|
||||
|
||||
// 初始化侧边栏功能
|
||||
function initializeSidebar() {
|
||||
const sidebarToggle = document.getElementById('sidebarToggle');
|
||||
const sidebarClose = document.getElementById('sidebarClose');
|
||||
const sidebar = document.getElementById('sidebar');
|
||||
|
||||
if (sidebarToggle && sidebarClose && sidebar) {
|
||||
// 切换侧边栏显示
|
||||
sidebarToggle.addEventListener('click', function() {
|
||||
sidebar.classList.add('show');
|
||||
document.body.style.overflow = 'hidden';
|
||||
});
|
||||
|
||||
// 关闭侧边栏
|
||||
sidebarClose.addEventListener('click', function() {
|
||||
sidebar.classList.remove('show');
|
||||
document.body.style.overflow = '';
|
||||
});
|
||||
|
||||
// 点击侧边栏外部关闭
|
||||
document.addEventListener('click', function(e) {
|
||||
if (window.innerWidth <= 768 &&
|
||||
sidebar.classList.contains('show') &&
|
||||
!sidebar.contains(e.target) &&
|
||||
!sidebarToggle.contains(e.target)) {
|
||||
sidebar.classList.remove('show');
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
});
|
||||
|
||||
// 窗口大小改变时重置侧边栏状态
|
||||
window.addEventListener('resize', function() {
|
||||
if (window.innerWidth > 768) {
|
||||
sidebar.classList.remove('show');
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 在页面加载时初始化侧边栏
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
initializeSidebar();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user