feat: 自动提交 - 周一 2025/09/22 16:50:40.70
This commit is contained in:
@@ -14,9 +14,68 @@ alerts_bp = Blueprint('alerts', __name__, url_prefix='/api/alerts')
|
|||||||
@alerts_bp.route('')
|
@alerts_bp.route('')
|
||||||
@handle_api_errors
|
@handle_api_errors
|
||||||
def get_alerts():
|
def get_alerts():
|
||||||
"""获取预警列表"""
|
"""获取预警列表(分页)"""
|
||||||
alerts = service_manager.get_assistant().get_active_alerts()
|
try:
|
||||||
return jsonify(alerts)
|
# 获取分页参数
|
||||||
|
page = request.args.get('page', 1, type=int)
|
||||||
|
per_page = request.args.get('per_page', 10, type=int)
|
||||||
|
level_filter = request.args.get('level', '')
|
||||||
|
status_filter = request.args.get('status', '')
|
||||||
|
|
||||||
|
# 从数据库获取分页数据
|
||||||
|
from src.core.database import db_manager
|
||||||
|
from src.core.models import Alert
|
||||||
|
|
||||||
|
with db_manager.get_session() as session:
|
||||||
|
# 构建查询
|
||||||
|
query = session.query(Alert)
|
||||||
|
|
||||||
|
# 应用过滤器
|
||||||
|
if level_filter:
|
||||||
|
query = query.filter(Alert.level == level_filter)
|
||||||
|
if status_filter:
|
||||||
|
if status_filter == 'active':
|
||||||
|
query = query.filter(Alert.status == 'active')
|
||||||
|
elif status_filter == 'resolved':
|
||||||
|
query = query.filter(Alert.status == 'resolved')
|
||||||
|
|
||||||
|
# 按创建时间倒序排列
|
||||||
|
query = query.order_by(Alert.created_at.desc())
|
||||||
|
|
||||||
|
# 计算总数
|
||||||
|
total = query.count()
|
||||||
|
|
||||||
|
# 分页查询
|
||||||
|
alerts = query.offset((page - 1) * per_page).limit(per_page).all()
|
||||||
|
|
||||||
|
# 转换为字典
|
||||||
|
alerts_data = []
|
||||||
|
for alert in alerts:
|
||||||
|
alerts_data.append({
|
||||||
|
'id': alert.id,
|
||||||
|
'rule_name': alert.rule_name,
|
||||||
|
'message': alert.message,
|
||||||
|
'level': alert.level,
|
||||||
|
'status': alert.status,
|
||||||
|
'source': alert.source,
|
||||||
|
'metadata': alert.metadata,
|
||||||
|
'created_at': alert.created_at.isoformat() if alert.created_at else None,
|
||||||
|
'resolved_at': alert.resolved_at.isoformat() if alert.resolved_at else None
|
||||||
|
})
|
||||||
|
|
||||||
|
# 计算分页信息
|
||||||
|
total_pages = (total + per_page - 1) // per_page
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'alerts': alerts_data,
|
||||||
|
'page': page,
|
||||||
|
'per_page': per_page,
|
||||||
|
'total': total,
|
||||||
|
'total_pages': total_pages
|
||||||
|
})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return create_error_response(f"获取预警列表失败: {str(e)}", 500)
|
||||||
|
|
||||||
@alerts_bp.route('', methods=['POST'])
|
@alerts_bp.route('', methods=['POST'])
|
||||||
def create_alert():
|
def create_alert():
|
||||||
|
|||||||
@@ -29,18 +29,67 @@ def get_agent_assistant():
|
|||||||
|
|
||||||
@knowledge_bp.route('')
|
@knowledge_bp.route('')
|
||||||
def get_knowledge():
|
def get_knowledge():
|
||||||
"""获取知识库列表"""
|
"""获取知识库列表(分页)"""
|
||||||
try:
|
try:
|
||||||
# 获取分页参数
|
# 获取分页参数
|
||||||
page = request.args.get('page', 1, type=int)
|
page = request.args.get('page', 1, type=int)
|
||||||
per_page = request.args.get('per_page', 10, type=int)
|
per_page = request.args.get('per_page', 10, type=int)
|
||||||
|
category_filter = request.args.get('category', '')
|
||||||
|
verified_filter = request.args.get('verified', '')
|
||||||
|
|
||||||
# 从数据库获取知识库数据
|
# 从数据库获取知识库数据
|
||||||
knowledge_entries = get_assistant().knowledge_manager.get_knowledge_entries(
|
from src.core.database import db_manager
|
||||||
page=page, per_page=per_page
|
from src.core.models import KnowledgeEntry
|
||||||
)
|
|
||||||
|
|
||||||
return jsonify(knowledge_entries)
|
with db_manager.get_session() as session:
|
||||||
|
# 构建查询
|
||||||
|
query = session.query(KnowledgeEntry).filter(KnowledgeEntry.is_active == True)
|
||||||
|
|
||||||
|
# 应用过滤器
|
||||||
|
if category_filter:
|
||||||
|
query = query.filter(KnowledgeEntry.category == category_filter)
|
||||||
|
if verified_filter:
|
||||||
|
if verified_filter == 'true':
|
||||||
|
query = query.filter(KnowledgeEntry.is_verified == True)
|
||||||
|
elif verified_filter == 'false':
|
||||||
|
query = query.filter(KnowledgeEntry.is_verified == False)
|
||||||
|
|
||||||
|
# 按创建时间倒序排列
|
||||||
|
query = query.order_by(KnowledgeEntry.created_at.desc())
|
||||||
|
|
||||||
|
# 计算总数
|
||||||
|
total = query.count()
|
||||||
|
|
||||||
|
# 分页查询
|
||||||
|
knowledge_entries = query.offset((page - 1) * per_page).limit(per_page).all()
|
||||||
|
|
||||||
|
# 转换为字典
|
||||||
|
knowledge_data = []
|
||||||
|
for entry in knowledge_entries:
|
||||||
|
knowledge_data.append({
|
||||||
|
'id': entry.id,
|
||||||
|
'question': entry.question,
|
||||||
|
'answer': entry.answer,
|
||||||
|
'category': entry.category,
|
||||||
|
'confidence_score': entry.confidence_score,
|
||||||
|
'usage_count': entry.usage_count,
|
||||||
|
'is_verified': entry.is_verified,
|
||||||
|
'is_active': entry.is_active,
|
||||||
|
'created_at': entry.created_at.isoformat() if entry.created_at else None,
|
||||||
|
'updated_at': entry.updated_at.isoformat() if entry.updated_at else None
|
||||||
|
})
|
||||||
|
|
||||||
|
# 计算分页信息
|
||||||
|
total_pages = (total + per_page - 1) // per_page
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'knowledge': knowledge_data,
|
||||||
|
'page': page,
|
||||||
|
'per_page': per_page,
|
||||||
|
'total': total,
|
||||||
|
'total_pages': total_pages
|
||||||
|
})
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({"error": str(e)}), 500
|
return jsonify({"error": str(e)}), 500
|
||||||
|
|
||||||
|
|||||||
@@ -100,17 +100,66 @@ def _ensure_workorder_template_file() -> str:
|
|||||||
|
|
||||||
@workorders_bp.route('')
|
@workorders_bp.route('')
|
||||||
def get_workorders():
|
def get_workorders():
|
||||||
"""获取工单列表(优化版)"""
|
"""获取工单列表(分页)"""
|
||||||
try:
|
try:
|
||||||
|
# 获取分页参数
|
||||||
|
page = request.args.get('page', 1, type=int)
|
||||||
|
per_page = request.args.get('per_page', 10, type=int)
|
||||||
status_filter = request.args.get('status', '')
|
status_filter = request.args.get('status', '')
|
||||||
priority_filter = request.args.get('priority', '')
|
priority_filter = request.args.get('priority', '')
|
||||||
|
|
||||||
# 使用优化后的查询
|
# 从数据库获取分页数据
|
||||||
result = query_optimizer.get_workorders_optimized(
|
from src.core.database import db_manager
|
||||||
status_filter=status_filter, priority_filter=priority_filter
|
from src.core.models import WorkOrder
|
||||||
)
|
|
||||||
|
|
||||||
return jsonify(result)
|
with db_manager.get_session() as session:
|
||||||
|
# 构建查询
|
||||||
|
query = session.query(WorkOrder)
|
||||||
|
|
||||||
|
# 应用过滤器
|
||||||
|
if status_filter:
|
||||||
|
query = query.filter(WorkOrder.status == status_filter)
|
||||||
|
if priority_filter:
|
||||||
|
query = query.filter(WorkOrder.priority == priority_filter)
|
||||||
|
|
||||||
|
# 按创建时间倒序排列
|
||||||
|
query = query.order_by(WorkOrder.created_at.desc())
|
||||||
|
|
||||||
|
# 计算总数
|
||||||
|
total = query.count()
|
||||||
|
|
||||||
|
# 分页查询
|
||||||
|
workorders = query.offset((page - 1) * per_page).limit(per_page).all()
|
||||||
|
|
||||||
|
# 转换为字典
|
||||||
|
workorders_data = []
|
||||||
|
for workorder in workorders:
|
||||||
|
workorders_data.append({
|
||||||
|
'id': workorder.id,
|
||||||
|
'order_id': workorder.order_id,
|
||||||
|
'title': workorder.title,
|
||||||
|
'description': workorder.description,
|
||||||
|
'category': workorder.category,
|
||||||
|
'priority': workorder.priority,
|
||||||
|
'status': workorder.status,
|
||||||
|
'user_id': workorder.user_id,
|
||||||
|
'assigned_to': workorder.assigned_to,
|
||||||
|
'created_at': workorder.created_at.isoformat() if workorder.created_at else None,
|
||||||
|
'updated_at': workorder.updated_at.isoformat() if workorder.updated_at else None,
|
||||||
|
'resolved_at': workorder.resolved_at.isoformat() if workorder.resolved_at else None
|
||||||
|
})
|
||||||
|
|
||||||
|
# 计算分页信息
|
||||||
|
total_pages = (total + per_page - 1) // per_page
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'workorders': workorders_data,
|
||||||
|
'page': page,
|
||||||
|
'per_page': per_page,
|
||||||
|
'total': total,
|
||||||
|
'total_pages': total_pages
|
||||||
|
})
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({"error": str(e)}), 500
|
return jsonify({"error": str(e)}), 500
|
||||||
|
|
||||||
|
|||||||
@@ -149,6 +149,13 @@ class TSPDashboard {
|
|||||||
this.cache = new Map();
|
this.cache = new Map();
|
||||||
this.cacheTimeout = 30000; // 30秒缓存
|
this.cacheTimeout = 30000; // 30秒缓存
|
||||||
|
|
||||||
|
// 分页配置
|
||||||
|
this.paginationConfig = {
|
||||||
|
defaultPageSize: 10,
|
||||||
|
pageSizeOptions: [5, 10, 20, 50],
|
||||||
|
maxVisiblePages: 5
|
||||||
|
};
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
this.restorePageState();
|
this.restorePageState();
|
||||||
this.initLanguage();
|
this.initLanguage();
|
||||||
@@ -342,6 +349,123 @@ class TSPDashboard {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 统一分页组件
|
||||||
|
createPaginationComponent(data, containerId, loadFunction, itemName = '条记录') {
|
||||||
|
const paginationContainer = document.getElementById(containerId);
|
||||||
|
if (!paginationContainer) return;
|
||||||
|
|
||||||
|
const { page, total_pages, total, per_page } = data;
|
||||||
|
|
||||||
|
if (total_pages <= 1) {
|
||||||
|
paginationContainer.innerHTML = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let paginationHtml = `
|
||||||
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<small class="text-muted me-3">共 ${total} ${itemName},第 ${page} / ${total_pages} 页</small>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<label class="form-label me-2 mb-0">每页显示:</label>
|
||||||
|
<select class="form-select form-select-sm" style="width: auto;" onchange="dashboard.changePageSize('${containerId}', this.value, '${loadFunction}')">
|
||||||
|
`;
|
||||||
|
|
||||||
|
// 每页显示条数选择器
|
||||||
|
this.paginationConfig.pageSizeOptions.forEach(size => {
|
||||||
|
const selected = size === per_page ? 'selected' : '';
|
||||||
|
paginationHtml += `<option value="${size}" ${selected}>${size}</option>`;
|
||||||
|
});
|
||||||
|
|
||||||
|
paginationHtml += `
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<nav>
|
||||||
|
<ul class="pagination pagination-sm mb-0">
|
||||||
|
`;
|
||||||
|
|
||||||
|
// 上一页
|
||||||
|
if (page > 1) {
|
||||||
|
paginationHtml += `<li class="page-item"><a class="page-link" href="#" onclick="dashboard.loadPage('${loadFunction}', ${page - 1}, '${containerId}')">上一页</a></li>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页码
|
||||||
|
const startPage = Math.max(1, page - Math.floor(this.paginationConfig.maxVisiblePages / 2));
|
||||||
|
const endPage = Math.min(total_pages, startPage + this.paginationConfig.maxVisiblePages - 1);
|
||||||
|
|
||||||
|
// 如果开始页码大于1,显示第一页和省略号
|
||||||
|
if (startPage > 1) {
|
||||||
|
paginationHtml += `<li class="page-item"><a class="page-link" href="#" onclick="dashboard.loadPage('${loadFunction}', 1, '${containerId}')">1</a></li>`;
|
||||||
|
if (startPage > 2) {
|
||||||
|
paginationHtml += `<li class="page-item disabled"><span class="page-link">...</span></li>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示页码范围
|
||||||
|
for (let i = startPage; i <= endPage; i++) {
|
||||||
|
const activeClass = i === page ? 'active' : '';
|
||||||
|
paginationHtml += `<li class="page-item ${activeClass}"><a class="page-link" href="#" onclick="dashboard.loadPage('${loadFunction}', ${i}, '${containerId}')">${i}</a></li>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果结束页码小于总页数,显示省略号和最后一页
|
||||||
|
if (endPage < total_pages) {
|
||||||
|
if (endPage < total_pages - 1) {
|
||||||
|
paginationHtml += `<li class="page-item disabled"><span class="page-link">...</span></li>`;
|
||||||
|
}
|
||||||
|
paginationHtml += `<li class="page-item"><a class="page-link" href="#" onclick="dashboard.loadPage('${loadFunction}', ${total_pages}, '${containerId}')">${total_pages}</a></li>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下一页
|
||||||
|
if (page < total_pages) {
|
||||||
|
paginationHtml += `<li class="page-item"><a class="page-link" href="#" onclick="dashboard.loadPage('${loadFunction}', ${page + 1}, '${containerId}')">下一页</a></li>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
paginationHtml += `
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
paginationContainer.innerHTML = paginationHtml;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载指定页面
|
||||||
|
loadPage(loadFunction, page, containerId) {
|
||||||
|
const pageSize = this.getPageSize(containerId);
|
||||||
|
if (loadFunction === 'loadAlerts') {
|
||||||
|
this.loadAlerts(page, true);
|
||||||
|
} else if (loadFunction === 'loadWorkOrders') {
|
||||||
|
this.loadWorkOrders(page, true);
|
||||||
|
} else if (loadFunction === 'loadKnowledge') {
|
||||||
|
this.loadKnowledge(page);
|
||||||
|
} else if (loadFunction === 'loadConversationHistory') {
|
||||||
|
this.loadConversationHistory(page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 改变每页显示条数
|
||||||
|
changePageSize(containerId, pageSize, loadFunction) {
|
||||||
|
// 保存页面大小到localStorage
|
||||||
|
localStorage.setItem(`pageSize_${containerId}`, pageSize);
|
||||||
|
|
||||||
|
// 重新加载第一页
|
||||||
|
if (loadFunction === 'loadAlerts') {
|
||||||
|
this.loadAlerts(1, true);
|
||||||
|
} else if (loadFunction === 'loadWorkOrders') {
|
||||||
|
this.loadWorkOrders(1, true);
|
||||||
|
} else if (loadFunction === 'loadKnowledge') {
|
||||||
|
this.loadKnowledge(1);
|
||||||
|
} else if (loadFunction === 'loadConversationHistory') {
|
||||||
|
this.loadConversationHistory(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取页面大小
|
||||||
|
getPageSize(containerId) {
|
||||||
|
const saved = localStorage.getItem(`pageSize_${containerId}`);
|
||||||
|
return saved ? parseInt(saved) : this.paginationConfig.defaultPageSize;
|
||||||
|
}
|
||||||
|
|
||||||
setCachedData(key, data) {
|
setCachedData(key, data) {
|
||||||
this.cache.set(key, {
|
this.cache.set(key, {
|
||||||
@@ -1348,14 +1472,27 @@ class TSPDashboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 预警管理
|
// 预警管理
|
||||||
async loadAlerts() {
|
async loadAlerts(page = 1, forceRefresh = false) {
|
||||||
|
const cacheKey = `alerts_page_${page}`;
|
||||||
|
|
||||||
|
if (!forceRefresh && this.cache.has(cacheKey)) {
|
||||||
|
const cachedData = this.cache.get(cacheKey);
|
||||||
|
this.updateAlertsDisplay(cachedData.alerts);
|
||||||
|
this.updateAlertsPagination(cachedData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/alerts');
|
const pageSize = this.getPageSize('alerts-pagination');
|
||||||
const alerts = await response.json();
|
const response = await fetch(`/api/alerts?page=${page}&per_page=${pageSize}`);
|
||||||
this.updateAlertsDisplay(alerts);
|
const data = await response.json();
|
||||||
this.updateAlertStatistics(alerts);
|
|
||||||
|
this.cache.set(cacheKey, data);
|
||||||
|
this.updateAlertsDisplay(data.alerts);
|
||||||
|
this.updateAlertsPagination(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载预警失败:', error);
|
console.error('加载预警失败:', error);
|
||||||
|
this.showNotification('加载预警失败', 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1418,6 +1555,10 @@ class TSPDashboard {
|
|||||||
container.innerHTML = headerHtml + alertsHtml;
|
container.innerHTML = headerHtml + alertsHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateAlertsPagination(data) {
|
||||||
|
this.createPaginationComponent(data, 'alerts-pagination', 'loadAlerts', '条预警');
|
||||||
|
}
|
||||||
|
|
||||||
updateAlertStatistics(alerts) {
|
updateAlertStatistics(alerts) {
|
||||||
const stats = alerts.reduce((acc, alert) => {
|
const stats = alerts.reduce((acc, alert) => {
|
||||||
acc[alert.level] = (acc[alert.level] || 0) + 1;
|
acc[alert.level] = (acc[alert.level] || 0) + 1;
|
||||||
@@ -1517,7 +1658,8 @@ class TSPDashboard {
|
|||||||
// 知识库管理
|
// 知识库管理
|
||||||
async loadKnowledge(page = 1) {
|
async loadKnowledge(page = 1) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/api/knowledge?page=${page}&per_page=10`);
|
const pageSize = this.getPageSize('knowledge-pagination');
|
||||||
|
const response = await fetch(`/api/knowledge?page=${page}&per_page=${pageSize}`);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (data.knowledge) {
|
if (data.knowledge) {
|
||||||
@@ -1596,51 +1738,7 @@ class TSPDashboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateKnowledgePagination(data) {
|
updateKnowledgePagination(data) {
|
||||||
const paginationContainer = document.getElementById('knowledge-pagination');
|
this.createPaginationComponent(data, 'knowledge-pagination', 'loadKnowledge', '条知识');
|
||||||
if (!paginationContainer) return;
|
|
||||||
|
|
||||||
const { page, total_pages, total } = data;
|
|
||||||
|
|
||||||
if (total_pages <= 1) {
|
|
||||||
paginationContainer.innerHTML = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let paginationHtml = `
|
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
|
||||||
<div>
|
|
||||||
<small class="text-muted">共 ${total} 条知识,第 ${page} / ${total_pages} 页</small>
|
|
||||||
</div>
|
|
||||||
<nav>
|
|
||||||
<ul class="pagination pagination-sm mb-0">
|
|
||||||
`;
|
|
||||||
|
|
||||||
// 上一页
|
|
||||||
if (page > 1) {
|
|
||||||
paginationHtml += `<li class="page-item"><a class="page-link" href="#" onclick="dashboard.loadKnowledge(${page - 1})">上一页</a></li>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 页码
|
|
||||||
const startPage = Math.max(1, page - 2);
|
|
||||||
const endPage = Math.min(total_pages, page + 2);
|
|
||||||
|
|
||||||
for (let i = startPage; i <= endPage; i++) {
|
|
||||||
const activeClass = i === page ? 'active' : '';
|
|
||||||
paginationHtml += `<li class="page-item ${activeClass}"><a class="page-link" href="#" onclick="dashboard.loadKnowledge(${i})">${i}</a></li>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下一页
|
|
||||||
if (page < total_pages) {
|
|
||||||
paginationHtml += `<li class="page-item"><a class="page-link" href="#" onclick="dashboard.loadKnowledge(${page + 1})">下一页</a></li>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
paginationHtml += `
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
paginationContainer.innerHTML = paginationHtml;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchKnowledge() {
|
async searchKnowledge() {
|
||||||
@@ -1919,13 +2017,25 @@ class TSPDashboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 工单管理
|
// 工单管理
|
||||||
async loadWorkOrders(forceRefresh = false) {
|
async loadWorkOrders(page = 1, forceRefresh = false) {
|
||||||
|
const cacheKey = `workorders_page_${page}`;
|
||||||
|
|
||||||
|
if (!forceRefresh && this.cache.has(cacheKey)) {
|
||||||
|
const cachedData = this.cache.get(cacheKey);
|
||||||
|
this.updateWorkOrdersDisplay(cachedData.workorders);
|
||||||
|
this.updateWorkOrdersPagination(cachedData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const statusFilter = document.getElementById('workorder-status-filter')?.value || 'all';
|
const statusFilter = document.getElementById('workorder-status-filter')?.value || 'all';
|
||||||
const priorityFilter = document.getElementById('workorder-priority-filter')?.value || 'all';
|
const priorityFilter = document.getElementById('workorder-priority-filter')?.value || 'all';
|
||||||
|
|
||||||
let url = '/api/workorders';
|
let url = '/api/workorders';
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
|
params.append('page', page);
|
||||||
|
const pageSize = this.getPageSize('workorders-pagination');
|
||||||
|
params.append('per_page', pageSize.toString());
|
||||||
if (statusFilter !== 'all') params.append('status', statusFilter);
|
if (statusFilter !== 'all') params.append('status', statusFilter);
|
||||||
if (priorityFilter !== 'all') params.append('priority', priorityFilter);
|
if (priorityFilter !== 'all') params.append('priority', priorityFilter);
|
||||||
|
|
||||||
@@ -1948,15 +2058,12 @@ class TSPDashboard {
|
|||||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const workorders = await response.json();
|
const data = await response.json();
|
||||||
this.updateWorkOrdersDisplay(workorders);
|
this.updateWorkOrdersDisplay(data.workorders);
|
||||||
this.updateWorkOrderStatistics(workorders);
|
this.updateWorkOrdersPagination(data);
|
||||||
|
|
||||||
// 更新缓存
|
// 更新缓存
|
||||||
this.cache.set('workorders', {
|
this.cache.set(cacheKey, data);
|
||||||
data: workorders,
|
|
||||||
timestamp: Date.now()
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载工单失败:', error);
|
console.error('加载工单失败:', error);
|
||||||
@@ -2023,6 +2130,10 @@ class TSPDashboard {
|
|||||||
container.innerHTML = headerHtml + workordersHtml;
|
container.innerHTML = headerHtml + workordersHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateWorkOrdersPagination(data) {
|
||||||
|
this.createPaginationComponent(data, 'workorders-pagination', 'loadWorkOrders', '个工单');
|
||||||
|
}
|
||||||
|
|
||||||
updateWorkOrderStatistics(workorders) {
|
updateWorkOrderStatistics(workorders) {
|
||||||
const stats = workorders.reduce((acc, wo) => {
|
const stats = workorders.reduce((acc, wo) => {
|
||||||
acc.total = (acc.total || 0) + 1;
|
acc.total = (acc.total || 0) + 1;
|
||||||
@@ -2626,14 +2737,15 @@ class TSPDashboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 对话历史管理
|
// 对话历史管理
|
||||||
async loadConversationHistory(page = 1, perPage = 10) {
|
async loadConversationHistory(page = 1) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/api/conversations?page=${page}&per_page=${perPage}`);
|
const pageSize = this.getPageSize('conversations-pagination');
|
||||||
|
const response = await fetch(`/api/conversations?page=${page}&per_page=${pageSize}`);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (data.success) {
|
if (data.conversations) {
|
||||||
this.renderConversationList(data.conversations || []);
|
this.renderConversationList(data.conversations || []);
|
||||||
this.renderConversationPagination(data.pagination || {});
|
this.updateConversationPagination(data);
|
||||||
this.updateConversationStats(data.stats || {});
|
this.updateConversationStats(data.stats || {});
|
||||||
} else {
|
} else {
|
||||||
throw new Error(data.error || '加载对话历史失败');
|
throw new Error(data.error || '加载对话历史失败');
|
||||||
@@ -2688,36 +2800,8 @@ class TSPDashboard {
|
|||||||
container.innerHTML = html;
|
container.innerHTML = html;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderConversationPagination(pagination) {
|
updateConversationPagination(data) {
|
||||||
const container = document.getElementById('conversation-pagination');
|
this.createPaginationComponent(data, 'conversations-pagination', 'loadConversationHistory', '条对话');
|
||||||
if (!pagination || !pagination.total_pages || pagination.total_pages <= 1) {
|
|
||||||
container.innerHTML = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentPage = pagination.current_page || 1;
|
|
||||||
const totalPages = pagination.total_pages;
|
|
||||||
|
|
||||||
let html = '<nav><ul class="pagination justify-content-center">';
|
|
||||||
|
|
||||||
// 上一页
|
|
||||||
if (currentPage > 1) {
|
|
||||||
html += `<li class="page-item"><a class="page-link" href="#" onclick="dashboard.loadConversationHistory(${currentPage - 1})">上一页</a></li>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 页码
|
|
||||||
for (let i = Math.max(1, currentPage - 2); i <= Math.min(totalPages, currentPage + 2); i++) {
|
|
||||||
const activeClass = i === currentPage ? 'active' : '';
|
|
||||||
html += `<li class="page-item ${activeClass}"><a class="page-link" href="#" onclick="dashboard.loadConversationHistory(${i})">${i}</a></li>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下一页
|
|
||||||
if (currentPage < totalPages) {
|
|
||||||
html += `<li class="page-item"><a class="page-link" href="#" onclick="dashboard.loadConversationHistory(${currentPage + 1})">下一页</a></li>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
html += '</ul></nav>';
|
|
||||||
container.innerHTML = html;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateConversationStats(stats) {
|
updateConversationStats(stats) {
|
||||||
|
|||||||
@@ -897,6 +897,9 @@
|
|||||||
<i class="fas fa-spinner fa-spin"></i>
|
<i class="fas fa-spinner fa-spin"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="alerts-pagination" class="mt-3">
|
||||||
|
<!-- 分页控件将在这里显示 -->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1015,6 +1018,9 @@
|
|||||||
<i class="fas fa-spinner fa-spin"></i>
|
<i class="fas fa-spinner fa-spin"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="workorders-pagination" class="mt-3">
|
||||||
|
<!-- 分页控件将在这里显示 -->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1305,7 +1311,7 @@
|
|||||||
<i class="fas fa-spinner fa-spin"></i>
|
<i class="fas fa-spinner fa-spin"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="conversation-pagination" class="mt-3">
|
<div id="conversations-pagination" class="mt-3">
|
||||||
<!-- 分页控件将在这里显示 -->
|
<!-- 分页控件将在这里显示 -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user