299 lines
7.8 KiB
HTML
Executable File
299 lines
7.8 KiB
HTML
Executable File
{% extends "base.html" %}
|
|
|
|
{% block content %}
|
|
{% include 'admin_nav.html' %}
|
|
|
|
<div class="admin-container">
|
|
<div class="admin-content">
|
|
<div class="admin-card">
|
|
<div class="card-header">
|
|
<div class="header-left">
|
|
<i class="fas fa-tablet-alt"></i>
|
|
<h3>平板应用筛选</h3>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="filter-form">
|
|
<textarea id="app-names" placeholder="请输入应用名称,批量输入用英文逗号分隔"></textarea>
|
|
<button onclick="filterTabletApps()" class="btn-primary">
|
|
<i class="fas fa-filter"></i> 开始筛选
|
|
</button>
|
|
</div>
|
|
|
|
<div class="filter-result-content" style="display: none;">
|
|
<div class="result-section">
|
|
<div class="success-section">
|
|
<div class="section-header">
|
|
<i class="fas fa-check-circle"></i>
|
|
<span class="success-count">成功: 0</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="failed-section">
|
|
<div class="section-header">
|
|
<i class="fas fa-times-circle"></i>
|
|
<span class="failed-count">失败: 0</span>
|
|
</div>
|
|
|
|
<div class="failed-category">
|
|
<div class="category-header">
|
|
<i class="fas fa-tablet-alt"></i>
|
|
<span>已在平板区</span>
|
|
</div>
|
|
<div class="failed-list exists-list"></div>
|
|
</div>
|
|
|
|
<div class="failed-category">
|
|
<div class="category-header">
|
|
<i class="fas fa-search"></i>
|
|
<span>未找到应用</span>
|
|
</div>
|
|
<div class="failed-list not-found-list"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.filter-form {
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
#app-names {
|
|
width: 100%;
|
|
height: 200px;
|
|
padding: 10px;
|
|
border: 1px solid #d2d2d7;
|
|
border-radius: 8px;
|
|
margin-bottom: 15px;
|
|
font-size: 14px;
|
|
resize: vertical;
|
|
}
|
|
|
|
.filter-result-content {
|
|
margin-top: 20px;
|
|
padding: 15px;
|
|
border-radius: 8px;
|
|
background: #f5f5f7;
|
|
}
|
|
|
|
.result-section {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 15px;
|
|
}
|
|
|
|
.success-section,
|
|
.failed-section {
|
|
padding: 15px;
|
|
border-radius: 8px;
|
|
background: white;
|
|
}
|
|
|
|
.section-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin-bottom: 10px;
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.success-section .section-header {
|
|
color: #34C759;
|
|
}
|
|
|
|
.failed-section .section-header {
|
|
color: #FF3B30;
|
|
}
|
|
|
|
.section-header i {
|
|
font-size: 18px;
|
|
}
|
|
|
|
.success-count,
|
|
.failed-count {
|
|
font-size: 14px;
|
|
}
|
|
|
|
/* 添加失败列表样式 */
|
|
.failed-list {
|
|
margin-top: 10px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
.failed-item {
|
|
padding: 12px 15px;
|
|
background: white;
|
|
border-radius: 6px;
|
|
font-size: 14px;
|
|
margin-bottom: 8px;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.failed-item .app-names {
|
|
font-weight: 500;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.failed-category {
|
|
margin-top: 15px;
|
|
background: #f8f9fa;
|
|
border-radius: 6px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.category-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 10px 12px;
|
|
background: #f1f1f1;
|
|
font-size: 14px;
|
|
color: #666;
|
|
}
|
|
|
|
.category-header i {
|
|
font-size: 14px;
|
|
}
|
|
|
|
.failed-list {
|
|
padding: 8px;
|
|
}
|
|
|
|
.failed-list:empty {
|
|
display: none;
|
|
}
|
|
|
|
.exists-list .failed-item {
|
|
border-left: 3px solid #007AFF;
|
|
}
|
|
|
|
.not-found-list .failed-item {
|
|
border-left: 3px solid #FF3B30;
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
function filterTabletApps() {
|
|
const appNames = document.getElementById('app-names').value
|
|
.split(',') // 改为用逗号分隔
|
|
.map(name => name.trim())
|
|
.filter(name => name);
|
|
|
|
if (!appNames.length) {
|
|
showNotification('请输入应用名称', 'error');
|
|
return;
|
|
}
|
|
|
|
fetch('{{ url_for("filter_tablet_apps") }}', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({ app_names: appNames })
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
showResults(data.results);
|
|
showNotification(data.message, 'success');
|
|
} else {
|
|
showNotification(data.error || '筛选失败', 'error');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
showNotification('筛选失败,请重试', 'error');
|
|
});
|
|
}
|
|
|
|
function showResults(results) {
|
|
const resultContent = document.querySelector('.filter-result-content');
|
|
const successCount = document.querySelector('.success-count');
|
|
const failedCount = document.querySelector('.failed-count');
|
|
const existsList = document.querySelector('.exists-list');
|
|
const notFoundList = document.querySelector('.not-found-list');
|
|
|
|
// 更新计数
|
|
successCount.textContent = `成功: ${results.success.length}`;
|
|
|
|
// 清空列表
|
|
existsList.innerHTML = '';
|
|
notFoundList.innerHTML = '';
|
|
|
|
// 收集分类的应用名称
|
|
let existsApps = [];
|
|
let notFoundApps = [];
|
|
|
|
// 分类收集应用名称
|
|
Object.entries(results.failed).forEach(([appName, reason]) => {
|
|
if (reason.includes('已在平板区')) {
|
|
existsApps.push(appName);
|
|
} else if (reason.includes('未找到')) {
|
|
notFoundApps.push(appName);
|
|
}
|
|
});
|
|
|
|
// 创建已存在应用的显示项
|
|
if (existsApps.length > 0) {
|
|
const existsItem = document.createElement('div');
|
|
existsItem.className = 'failed-item';
|
|
existsItem.innerHTML = `<span class="app-names">${existsApps.join(', ')}</span>`;
|
|
existsList.appendChild(existsItem);
|
|
}
|
|
|
|
// 创建未找到应用的显示项
|
|
if (notFoundApps.length > 0) {
|
|
const notFoundItem = document.createElement('div');
|
|
notFoundItem.className = 'failed-item';
|
|
notFoundItem.innerHTML = `<span class="app-names">${notFoundApps.join(', ')}</span>`;
|
|
notFoundList.appendChild(notFoundItem);
|
|
}
|
|
|
|
// 更新总失败数
|
|
failedCount.textContent = `失败: ${existsApps.length + notFoundApps.length}`;
|
|
|
|
// 显示结果区域
|
|
resultContent.style.display = 'block';
|
|
}
|
|
|
|
function showNotification(message, type = 'success') {
|
|
const notification = document.createElement('div');
|
|
notification.className = `notification ${type}`;
|
|
notification.textContent = message;
|
|
|
|
Object.assign(notification.style, {
|
|
position: 'fixed',
|
|
bottom: '20px',
|
|
right: '20px',
|
|
padding: '10px 20px',
|
|
borderRadius: '4px',
|
|
backgroundColor: type === 'success' ? '#4CAF50' : '#f44336',
|
|
color: 'white',
|
|
zIndex: '1000',
|
|
opacity: '0',
|
|
transform: 'translateY(20px)',
|
|
transition: 'all 0.3s ease'
|
|
});
|
|
|
|
document.body.appendChild(notification);
|
|
|
|
notification.offsetHeight;
|
|
|
|
notification.style.opacity = '1';
|
|
notification.style.transform = 'translateY(0)';
|
|
|
|
setTimeout(() => {
|
|
notification.style.opacity = '0';
|
|
notification.style.transform = 'translateY(20px)';
|
|
setTimeout(() => notification.remove(), 300);
|
|
}, 3000);
|
|
}
|
|
</script>
|
|
{% endblock %} |