sunpayus/templates/index.html

420 lines
20 KiB
HTML
Raw Permalink Normal View History

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>多 Agent 决策工作坊</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<div class="container">
<!-- 页面标题 -->
<header>
<h1>多 Agent 决策工作坊</h1>
<p>通过多角色辩论生成更全面的决策方案</p>
</header>
<!-- 创建工作坊按钮 -->
<button onclick="window.location.href='{{ url_for('create_workshop') }}'" class="btn-primary">创建新工作坊</button>
<!-- 流程指南 -->
<div class="card">
<h3>工作流程指南</h3>
<div class="process-indicator">
<div class="process-step">
<div class="process-step-number">1</div>
<div class="process-step-text">创建工作坊</div>
</div>
<div class="process-arrow"></div>
<div class="process-step">
<div class="process-step-number">2</div>
<div class="process-step-text">配置角色</div>
</div>
<div class="process-arrow"></div>
<div class="process-step">
<div class="process-step-number">3</div>
<div class="process-step-text">开始辩论</div>
</div>
<div class="process-arrow"></div>
<div class="process-step">
<div class="process-step-number">4</div>
<div class="process-step-text">查看结果</div>
</div>
</div>
</div>
<!-- 工作坊列表 -->
<div class="workshop-header">
<h2>工作坊列表</h2>
<!-- 多选选项和排序按钮 -->
<div class="header-actions">
<!-- 多选选项 -->
<div class="select-options">
<button id="multiSelectToggle" class="btn-secondary">多选</button>
</div>
<!-- 排序按钮 -->
<div class="sort-buttons">
<button onclick="sortWorkshops('time')" class="btn-secondary {% if sort_by == 'time' %}active{% endif %}">按时间排序</button>
<button onclick="sortWorkshops('name')" class="btn-secondary {% if sort_by == 'name' %}active{% endif %}">按名称首字母排序</button>
</div>
</div>
</div>
<!-- 批量操作按钮 -->
<div class="batch-actions" id="batchActions" style="display: none;">
<button onclick="batchDeleteWorkshops()" class="btn-danger">批量删除</button>
<span id="selectedCount">已选择 0 个工作坊</span>
</div>
<div class="workshop-list" id="workshopList">
{% if workshops %}
{% for workshop_id, workshop in workshops.items() %}
<div class="workshop-card">
<!-- 复选框 -->
<div class="card-checkbox" style="display: none;">
<input type="checkbox" class="workshop-checkbox" data-id="{{ workshop_id }}">
</div>
<h3>{{ workshop.name }}</h3>
<p>{{ workshop.goal }}</p>
<div class="workshop-details">
<p><strong>角色数量:</strong> {{ workshop.roles|length }}</p>
<p><strong>辩论内容:</strong> {{ workshop.debate_content|length }} 条观点</p>
<p><strong>创建时间:</strong> {{ workshop.created_at.strftime('%Y-%m-%d %H:%M') if workshop.created_at else '未知' }}</p>
{% if workshop.final_decision_time %}
<p><strong>最终决策时间:</strong> {{ workshop.final_decision_time.strftime('%Y-%m-%d %H:%M') }}</p>
{% endif %}
</div>
<!-- 最终决策 -->
<div class="final-decision">
<p><strong>最终决策:</strong>
{% if workshop.final_decision %}
<span class="decision-text">{{ workshop.final_decision }}</span>
{% else %}
<span class="decision-pending">决策尚未确定</span>
{% endif %}
</p>
</div>
<!-- 工作坊状态 -->
{% if workshop.roles|length > 0 and workshop.debate_content|length > 0 %}
<span class="status-badge completed">已完成辩论</span>
{% elif workshop.roles|length > 0 %}
<span class="status-badge active">已配置角色</span>
{% else %}
<span class="status-badge">已创建</span>
{% endif %}
<!-- 操作按钮 -->
<div class="workshop-actions">
<button onclick="window.location.href='{{ url_for('configure_roles', workshop_id=workshop_id) }}'" class="btn-secondary">配置角色</button>
<button onclick="window.location.href='{{ url_for('start_debate', workshop_id=workshop_id) }}'" class="btn-primary">开始辩论</button>
<button onclick="window.location.href='{{ url_for('show_results', workshop_id=workshop_id) }}'" class="btn-success">查看结果</button>
<button onclick="deleteWorkshop({{ workshop_id }})" class="btn-danger">删除</button>
</div>
</div>
{% endfor %}
{% else %}
<div class="card">
<div class="empty-state">
<button onclick="window.location.href='{{ url_for('create_workshop') }}'" class="btn-primary">创建第一个工作坊</button>
</div>
</div>
{% endif %}
</div>
</div>
<script>
// 无刷新排序工作坊
function sortWorkshops(sortBy) {
// 更新按钮的active状态
const buttons = document.querySelectorAll('.sort-buttons button');
buttons.forEach(button => {
button.classList.remove('active');
});
// 为当前点击的按钮添加active状态
if (sortBy === 'time') {
buttons[0].classList.add('active');
} else {
buttons[1].classList.add('active');
}
// 发送AJAX请求获取排序后的数据
// 将time转换为time_asc实现按时间升序排序
const sortParam = sortBy === 'time' ? 'time_asc' : sortBy;
fetch(`/api/workshops?sort_by=${sortParam}`)
.then(response => response.json())
.then(data => {
// 更新工作坊列表
const workshopList = document.getElementById('workshopList');
workshopList.innerHTML = '';
if (data.length > 0) {
data.forEach(workshop => {
// 创建工作坊卡片
const workshopCard = document.createElement('div');
workshopCard.className = 'workshop-card';
// 构建卡片内容
let cardContent = `
<!-- 复选框 -->
<div class="card-checkbox" style="display: none;">
<input type="checkbox" class="workshop-checkbox" data-id="${workshop.id}">
</div>
<h3>${workshop.name}</h3>
<p>${workshop.goal}</p>
<div class="workshop-details">
<p><strong>角色数量:</strong> ${workshop.roles.length}</p>
<p><strong>辩论内容:</strong> ${workshop.debate_content.length} 条观点</p>
<p><strong>创建时间:</strong> ${workshop.created_at || '未知'}</p>
`;
// 添加最终决策时间(如果有)
if (workshop.final_decision_time) {
cardContent += `
<p><strong>最终决策时间:</strong> ${workshop.final_decision_time}</p>
`;
}
// 添加最终决策
cardContent += `
</div>
<!-- 最终决策 -->
<div class="final-decision">
<p><strong>最终决策:</strong>
`;
// 添加最终决策内容
if (workshop.final_decision) {
cardContent += `
<span class="decision-text">${workshop.final_decision}</span>
`;
} else {
cardContent += `
<span class="no-decision">暂无</span>
`;
}
// 添加工作坊状态
cardContent += `
</p>
</div>
<!-- 工作坊状态 -->
`;
if (workshop.roles.length > 0 && workshop.debate_content.length > 0) {
cardContent += `
<span class="status-badge completed">已完成辩论</span>
`;
} else if (workshop.roles.length > 0) {
cardContent += `
<span class="status-badge active">已配置角色</span>
`;
} else {
cardContent += `
<span class="status-badge">已创建</span>
`;
}
// 添加操作按钮
cardContent += `
<!-- 操作按钮 -->
<div class="workshop-actions">
<button onclick="window.location.href='/workshop/${workshop.id}/configure_roles'" class="btn-secondary">配置角色</button>
<button onclick="window.location.href='/workshop/${workshop.id}/debate'" class="btn-primary">开始辩论</button>
<button onclick="window.location.href='/workshop/${workshop.id}/results'" class="btn-success">查看结果</button>
<button onclick="deleteWorkshop(${workshop.id})" class="btn-danger">删除</button>
</div>
`;
workshopCard.innerHTML = cardContent;
workshopList.appendChild(workshopCard);
});
} else {
// 显示空状态
workshopList.innerHTML = `
<div class="card">
<div class="empty-state">
<p>暂无工作坊,请创建新工作坊</p>
<button onclick="window.location.href='/create'" class="btn-primary">创建第一个工作坊</button>
</div>
</div>
`;
}
})
.catch(error => {
console.error('获取数据失败:', error);
});
}
// 删除单个工作坊
function deleteWorkshop(id) {
if (confirm('确定要删除这个工作坊吗?')) {
fetch(`/api/workshop/${id}`, {
method: 'DELETE'
})
.then(response => response.json())
.then(data => {
if (data.success) {
// 重新获取工作坊列表
sortWorkshops(document.querySelector('.sort-buttons button.active') ? 'name' : 'time');
} else {
alert('删除失败: ' + data.message);
}
})
.catch(error => {
console.error('删除失败:', error);
alert('删除失败,请稍后重试');
});
}
}
// 批量删除工作坊
function batchDeleteWorkshops() {
const selectedIds = getSelectedWorkshopIds();
if (selectedIds.length === 0) {
alert('请先选择要删除的工作坊');
return;
}
if (confirm(`确定要删除选中的 ${selectedIds.length} 个工作坊吗?`)) {
fetch('/api/workshops/batch_delete', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ workshop_ids: selectedIds })
})
.then(response => response.json())
.then(data => {
if (data.success) {
// 重新获取工作坊列表
sortWorkshops(document.querySelector('.sort-buttons button.active') ? 'name' : 'time');
} else {
alert('批量删除失败: ' + data.message);
}
})
.catch(error => {
console.error('批量删除失败:', error);
alert('批量删除失败,请稍后重试');
});
}
}
// 获取选中的工作坊ID
function getSelectedWorkshopIds() {
const checkboxes = document.querySelectorAll('.workshop-checkbox:checked');
return Array.from(checkboxes).map(checkbox => parseInt(checkbox.dataset.id));
}
// 更新选中状态
function updateSelectionStatus() {
const selectedIds = getSelectedWorkshopIds();
const selectedCount = selectedIds.length;
const batchActions = document.getElementById('batchActions');
const selectedCountElement = document.getElementById('selectedCount');
if (selectedCount > 0) {
batchActions.style.display = 'flex';
selectedCountElement.textContent = `已选择 ${selectedCount} 个工作坊`;
} else {
batchActions.style.display = 'none';
}
// 更新全选复选框状态
const allCheckboxes = document.querySelectorAll('.workshop-checkbox');
const selectAllCheckbox = document.getElementById('selectAllCheckbox');
if (selectAllCheckbox) {
if (allCheckboxes.length > 0) {
selectAllCheckbox.checked = allCheckboxes.length === selectedIds.length;
} else {
selectAllCheckbox.checked = false;
}
}
}
// 切换多选模式
let isMultiSelectMode = false;
function toggleMultiSelectMode() {
const checkboxes = document.querySelectorAll('.card-checkbox');
// 检查是否有工作坊(即是否有复选框)
if (checkboxes.length === 0) {
return; // 没有工作坊时,不执行任何操作
}
isMultiSelectMode = !isMultiSelectMode;
const multiSelectToggle = document.getElementById('multiSelectToggle');
const batchActions = document.getElementById('batchActions');
if (isMultiSelectMode) {
// 进入多选模式
checkboxes.forEach(checkbox => {
checkbox.style.display = 'block';
});
multiSelectToggle.textContent = '取消多选';
multiSelectToggle.classList.remove('btn-secondary');
multiSelectToggle.classList.add('btn-primary');
// 显示批量操作按钮
batchActions.style.display = 'flex';
// 重置选中状态
document.querySelectorAll('.workshop-checkbox').forEach(checkbox => {
checkbox.checked = false;
});
updateSelectionStatus();
} else {
// 退出多选模式
checkboxes.forEach(checkbox => {
checkbox.style.display = 'none';
});
multiSelectToggle.textContent = '多选';
multiSelectToggle.classList.remove('btn-primary');
multiSelectToggle.classList.add('btn-secondary');
// 隐藏批量操作按钮
batchActions.style.display = 'none';
}
}
// 全选/取消全选
function toggleSelectAll() {
const checkboxes = document.querySelectorAll('.workshop-checkbox');
const firstCheckbox = checkboxes[0];
if (firstCheckbox) {
const shouldCheck = !firstCheckbox.checked;
checkboxes.forEach(checkbox => {
checkbox.checked = shouldCheck;
});
updateSelectionStatus();
}
}
// 监听工作坊复选框变化
document.addEventListener('change', function(event) {
if (event.target.classList.contains('workshop-checkbox')) {
updateSelectionStatus();
}
});
// 初始化时绑定事件
document.addEventListener('DOMContentLoaded', function() {
// 绑定排序按钮事件
const sortButtons = document.querySelectorAll('.sort-buttons button');
sortButtons.forEach(button => {
button.addEventListener('click', function() {
const sortBy = this.textContent.includes('时间') ? 'time' : 'name';
sortWorkshops(sortBy);
});
});
// 绑定多选模式切换按钮事件
const multiSelectToggle = document.getElementById('multiSelectToggle');
multiSelectToggle.addEventListener('click', toggleMultiSelectMode);
// 初始更新选中状态
updateSelectionStatus();
});
</script>
</body>
</html>