显示优化

This commit is contained in:
rjb
2025-10-17 23:26:07 +08:00
parent 44a9f3ffcc
commit 4129d63afc
7 changed files with 397 additions and 13 deletions

View File

@@ -177,13 +177,24 @@ def get_template_icon(category):
@main_bp.route('/', methods=['GET', 'POST'])
def index():
form = PromptForm()
templates = PromptTemplate.query.all()
# 获取所有可用的分类选项
industries = sorted(set(t.industry for t in templates if t.industry))
professions = sorted(set(t.profession for t in templates if t.profession))
categories = sorted(set(t.category for t in templates if t.category))
sub_categories = sorted(set(t.sub_category for t in templates if t.sub_category))
# 获取所有模板用于分类选项
all_templates = PromptTemplate.query.all()
# 默认只显示"通用"分类的模板,提升加载性能
templates = PromptTemplate.query.filter_by(category="通用").all()
# 获取所有可用的分类选项(基于所有模板)
industries = sorted(set(t.industry for t in all_templates if t.industry))
professions = sorted(set(t.profession for t in all_templates if t.profession))
# 特殊处理分类排序,让"通用"分类排在第一位
all_categories = sorted(set(t.category for t in all_templates if t.category))
categories = []
if "通用" in all_categories:
categories.append("通用")
all_categories.remove("通用")
categories.extend(all_categories)
sub_categories = sorted(set(t.sub_category for t in all_templates if t.sub_category))
if form.validate_on_submit():
template_id = request.form.get('template_id')
@@ -231,6 +242,35 @@ def index():
professions=professions, categories=categories,
sub_categories=sub_categories)
@main_bp.route('/api/templates/<category>')
def get_templates_by_category(category):
"""根据分类获取模板的API端点"""
if category == "all":
templates = PromptTemplate.query.all()
else:
templates = PromptTemplate.query.filter_by(category=category).all()
# 将模板转换为字典格式
template_list = []
for template in templates:
template_dict = {
'id': template.id,
'name': template.name,
'description': template.description,
'category': template.category,
'industry': template.industry,
'profession': template.profession,
'sub_category': template.sub_category,
'system_prompt': template.system_prompt
}
template_list.append(template_dict)
return jsonify({
'success': True,
'templates': template_list,
'count': len(template_list)
})
@main_bp.route('/prompt/<int:prompt_id>')
def show_prompt(prompt_id):
prompt = Prompt.query.get_or_404(prompt_id)

View File

@@ -57,9 +57,13 @@
<!-- 场景分类 -->
<div class="sidebar-categories">
<div class="category-tabs">
<div class="tab active" data-category="all">全部</div>
<div class="tab" data-category="all">全部</div>
{% for category in categories %}
{% if category == "通用" %}
<div class="tab active" data-category="{{ category }}">{{ category }}</div>
{% else %}
<div class="tab" data-category="{{ category }}">{{ category }}</div>
{% endif %}
{% endfor %}
</div>
</div>
@@ -2602,6 +2606,45 @@
.action-section {
animation: slideInUp 0.6s ease-out 0.5s both;
}
/* 加载状态样式 */
.loading-spinner {
text-align: center;
padding: 2rem;
color: #666;
font-size: 1.1rem;
}
.loading-spinner::before {
content: '';
display: inline-block;
width: 20px;
height: 20px;
border: 2px solid #f3f3f3;
border-top: 2px solid #007bff;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-right: 10px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.error-message {
text-align: center;
padding: 2rem;
color: #dc3545;
font-size: 1.1rem;
}
.no-templates {
text-align: center;
padding: 2rem;
color: #666;
font-size: 1.1rem;
}
</style>
<script>
@@ -2714,7 +2757,13 @@ document.addEventListener('DOMContentLoaded', function() {
professionFilter.value = 'all';
subCategoryFilter.value = 'all';
document.querySelector('.tab.active').classList.remove('active');
document.querySelector('[data-category="all"]').classList.add('active');
// 默认选中通用分类而不是全部
const generalTab = document.querySelector('[data-category="通用"]');
if (generalTab) {
generalTab.classList.add('active');
} else {
document.querySelector('[data-category="all"]').classList.add('active');
}
filterTemplates();
}
@@ -2727,12 +2776,164 @@ document.addEventListener('DOMContentLoaded', function() {
tab.addEventListener('click', () => {
tabs.forEach(t => t.classList.remove('active'));
tab.classList.add('active');
filterTemplates();
// 动态加载分类模板
const category = tab.dataset.category;
loadTemplatesByCategory(category);
});
});
// 初始化筛选
filterTemplates();
// 动态加载分类模板的函数
function loadTemplatesByCategory(category) {
// 显示加载状态
const templateGrid = document.querySelector('.template-grid');
if (templateGrid) {
templateGrid.innerHTML = '<div class="loading-spinner">正在加载模板...</div>';
}
// 发送AJAX请求获取模板
fetch(`/api/templates/${category}`)
.then(response => response.json())
.then(data => {
if (data.success) {
renderTemplates(data.templates);
} else {
console.error('加载模板失败');
}
})
.catch(error => {
console.error('加载模板出错:', error);
templateGrid.innerHTML = '<div class="error-message">加载失败,请刷新页面重试</div>';
});
}
// 渲染模板到页面
function renderTemplates(templates) {
const templateGrid = document.querySelector('.template-grid');
if (!templateGrid) return;
if (templates.length === 0) {
templateGrid.innerHTML = '<div class="no-templates">该分类下暂无模板</div>';
return;
}
let html = '';
templates.forEach(template => {
html += `
<div class="template-card"
data-category="${template.category || ''}"
data-industry="${template.industry || ''}"
data-profession="${template.profession || ''}"
data-subcategory="${template.sub_category || ''}"
data-template-id="${template.id}"
data-template-content="${template.system_prompt}">
<div class="template-header">
<div class="template-icon">
<i class="fas fa-star"></i>
</div>
<h3>${template.name}</h3>
</div>
<div class="template-badges">
<span class="badge badge-primary">${template.category || '未分类'}</span>
</div>
<div class="template-content">
<p class="template-description">${template.description || '暂无描述'}</p>
<div class="template-meta">
<span class="usage-count">0 次使用</span>
<span class="difficulty-level">初级</span>
</div>
<div class="template-fields">
<div class="field">
<span class="field-label">行业:</span>
<span class="field-value">${template.industry || '未设置'}</span>
</div>
<div class="field">
<span class="field-label">职业:</span>
<span class="field-value">${template.profession || '未设置'}</span>
</div>
<div class="field">
<span class="field-label">领域:</span>
<span class="field-value">${template.sub_category || '未设置'}</span>
</div>
</div>
</div>
<div class="template-actions">
<input type="radio" name="template_id" value="${template.id}" id="template_${template.id}">
<label for="template_${template.id}" class="template-label">
<span class="radio-custom"></span>
<span class="label-text">选择此模板</span>
</label>
<button type="button" class="btn-copy" onclick="copyText('${template.system_prompt.replace(/'/g, "\\'")}')">
<i class="fas fa-copy"></i>
复制内容
</button>
</div>
<div class="template-preview" style="display: none;">
<div class="preview-header">
<h4>${template.name}</h4>
<button type="button" class="preview-close">
<i class="fas fa-times"></i>
</button>
</div>
<div class="preview-content">
<h5>模板内容</h5>
<div class="preview-text">${template.system_prompt}</div>
<h5>使用说明</h5>
<div class="preview-description">${template.description || '暂无使用说明'}</div>
</div>
</div>
</div>
`;
});
templateGrid.innerHTML = html;
// 重新绑定事件
initializeTemplateEvents();
}
// 初始化模板事件
function initializeTemplateEvents() {
// 绑定模板选择事件
document.querySelectorAll('input[name="template_id"]').forEach(radio => {
radio.addEventListener('change', function() {
document.querySelectorAll('.template-card').forEach(card => {
card.classList.remove('selected');
});
if (this.checked) {
this.closest('.template-card').classList.add('selected');
}
});
});
// 绑定复制按钮事件
document.querySelectorAll('.btn-copy').forEach(button => {
button.addEventListener('click', function(e) {
e.preventDefault();
const text = this.closest('.template-card').dataset.templateContent;
copyText(text);
});
});
}
// 初始化筛选 - 默认选中通用分类
// 确保通用分类被选中
const generalTab = document.querySelector('[data-category="通用"]');
if (generalTab) {
// 移除所有active类
document.querySelectorAll('.tab').forEach(tab => tab.classList.remove('active'));
// 选中通用分类
generalTab.classList.add('active');
}
// 页面初始加载时不需要调用filterTemplates因为模板已经通过服务器端筛选了
});
function copyText(text) {
@@ -3788,7 +3989,13 @@ function performSearchAndFilter() {
document.getElementById('professionFilter').value = 'all';
document.getElementById('subCategoryFilter').value = 'all';
document.querySelectorAll('.tab').forEach(tab => tab.classList.remove('active'));
document.querySelector('[data-category="all"]').classList.add('active');
// 默认选中通用分类而不是全部
const generalTab = document.querySelector('[data-category="通用"]');
if (generalTab) {
generalTab.classList.add('active');
} else {
document.querySelector('[data-category="all"]').classList.add('active');
}
performSearchAndFilter();
});
}