Kamixitong/app/web/templates/license/export.html

242 lines
9.7 KiB
HTML
Raw Normal View History

2025-11-17 12:56:43 +08:00
{% extends "base.html" %}
{% block title %}导出卡密 - 软件授权管理系统{% endblock %}
{% block page_title %}导出卡密{% endblock %}
{% block page_actions %}
<a href="{{ url_for('web.licenses') }}" class="btn btn-outline-secondary">
<i class="fas fa-arrow-left me-2"></i>
返回列表
</a>
{% endblock %}
{% block content %}
<div class="row">
<div class="col-lg-8">
<div class="card shadow">
<div class="card-body">
<form id="export-form">
<div class="mb-3">
<label for="product_id" class="form-label">选择产品</label>
<select class="form-select" id="product_id" name="product_id">
<option value="">全部产品</option>
{% for product in products %}
<option value="{{ product.product_id }}">{{ product.product_name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label for="status" class="form-label">卡密状态</label>
<select class="form-select" id="status" name="status">
<option value="">全部状态</option>
<option value="0">未激活</option>
<option value="1">已激活</option>
<option value="2">已过期</option>
<option value="3">已禁用</option>
</select>
</div>
<div class="mb-3">
<label for="type" class="form-label">卡密类型</label>
<select class="form-select" id="type" name="type">
<option value="">全部类型</option>
<option value="1">正式卡密</option>
<option value="0">试用卡密</option>
</select>
</div>
<div class="mb-3">
<label for="format" class="form-label">导出格式 *</label>
<select class="form-select" id="format" name="format" required>
<option value="excel">Excel (.xlsx)</option>
<option value="csv">CSV (.csv)</option>
</select>
</div>
<button type="submit" class="btn btn-success" id="submit-btn">
<i class="fas fa-file-export me-2"></i>
<span id="submit-text">导出卡密</span>
</button>
<a href="{{ url_for('web.licenses') }}" class="btn btn-secondary">取消</a>
</form>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="card shadow">
<div class="card-header">
<h6 class="mb-0">导出说明</h6>
</div>
<div class="card-body">
<ul class="list-unstyled">
<li class="mb-2">
<i class="fas fa-info-circle text-primary me-2"></i>
<small>可以选择特定产品、状态和类型的卡密进行导出</small>
</li>
<li class="mb-2">
<i class="fas fa-info-circle text-primary me-2"></i>
<small>导出格式支持Excel和CSV两种</small>
</li>
<li class="mb-2">
<i class="fas fa-info-circle text-primary me-2"></i>
<small>导出的文件包含卡密、产品、状态、有效期等详细信息</small>
</li>
<li class="mb-2">
<i class="fas fa-info-circle text-primary me-2"></i>
<small>导出操作可能需要一些时间,请耐心等待</small>
</li>
</ul>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script>
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
initEventListeners();
});
// 初始化事件监听器
function initEventListeners() {
// 表单提交
document.getElementById('export-form').addEventListener('submit', function(e) {
e.preventDefault();
exportLicenses();
});
}
// 导出卡密
function exportLicenses() {
const submitBtn = document.getElementById('submit-btn');
const submitText = document.getElementById('submit-text');
// 获取表单数据
const formData = {
product_id: document.getElementById('product_id').value || null,
status: document.getElementById('status').value ? parseInt(document.getElementById('status').value) : null,
type: document.getElementById('type').value ? parseInt(document.getElementById('type').value) : null,
format: document.getElementById('format').value
};
// 显示加载状态
submitBtn.disabled = true;
submitText.textContent = '导出中...';
2025-11-28 15:56:33 +08:00
showLoading();
2025-11-17 12:56:43 +08:00
2025-11-28 15:56:33 +08:00
// 构建API URL复用base.html中的URL构建逻辑
let apiUrl = '/api/v1/licenses/export';
const frontendDomain = window.FRONTEND_DOMAIN || '';
2025-11-17 12:56:43 +08:00
2025-11-28 15:56:33 +08:00
if (apiUrl.startsWith('/')) {
if (frontendDomain && !apiUrl.startsWith(frontendDomain)) {
let cleanDomain = frontendDomain;
try {
const urlObj = new URL(frontendDomain.startsWith('http') ? frontendDomain : 'http://' + frontendDomain);
cleanDomain = urlObj.origin;
} catch (e) {
if (frontendDomain.includes('/')) {
cleanDomain = frontendDomain.split('/')[0];
}
}
apiUrl = cleanDomain + apiUrl;
} else if (!frontendDomain) {
apiUrl = window.location.origin + apiUrl;
}
}
// 直接使用fetch处理文件下载不使用apiRequest因为apiRequest会尝试解析JSON
fetch(apiUrl, {
2025-11-17 12:56:43 +08:00
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
2025-11-28 15:56:33 +08:00
credentials: 'same-origin',
2025-11-17 12:56:43 +08:00
body: JSON.stringify(formData)
})
.then(response => {
hideLoading();
2025-11-28 15:56:33 +08:00
// 检查响应状态
2025-11-17 12:56:43 +08:00
if (!response.ok) {
// 处理错误响应
if (response.status === 401) {
showNotification('会话已过期,请重新登录', 'warning');
setTimeout(() => {
window.location.href = '/login';
}, 1500);
throw new Error('未授权访问');
} else if (response.status === 403) {
return response.json().then(errorData => {
showNotification(errorData.message || '权限不足,无法执行此操作', 'error');
throw new Error(`403: ${errorData.message || '权限不足'}`);
2025-11-28 15:56:33 +08:00
}).catch(() => {
showNotification('权限不足,无法执行此操作', 'error');
throw new Error('403: 权限不足');
2025-11-17 12:56:43 +08:00
});
} else {
2025-11-28 15:56:33 +08:00
// 尝试解析错误信息
2025-11-17 12:56:43 +08:00
return response.json().then(errorData => {
2025-11-28 15:56:33 +08:00
showNotification(errorData.message || `导出失败: ${response.statusText}`, 'error');
2025-11-17 12:56:43 +08:00
throw new Error(`${response.status}: ${errorData.message || response.statusText}`);
2025-11-28 15:56:33 +08:00
}).catch(() => {
showNotification(`导出失败: ${response.statusText}`, 'error');
throw new Error(`${response.status}: ${response.statusText}`);
2025-11-17 12:56:43 +08:00
});
}
}
2025-11-28 15:56:33 +08:00
// 成功响应,处理文件下载
2025-11-17 12:56:43 +08:00
// 获取文件名
const contentDisposition = response.headers.get('Content-Disposition');
let filename = 'licenses.xlsx';
if (contentDisposition) {
2025-11-28 15:56:33 +08:00
const filenameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
if (filenameMatch && filenameMatch[1]) {
filename = filenameMatch[1].replace(/['"]/g, '');
// 处理URL编码的文件名
try {
filename = decodeURIComponent(filename);
} catch (e) {
// 如果解码失败,使用原始文件名
}
2025-11-17 12:56:43 +08:00
}
}
// 下载文件
return response.blob().then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
showNotification('导出成功', 'success');
});
})
.catch(error => {
hideLoading();
console.error('Failed to export licenses:', error);
2025-11-28 15:56:33 +08:00
// 如果错误消息不是我们自定义的,显示通用错误消息
if (error.message && !error.message.includes(':')) {
showNotification('导出失败: ' + error.message, 'error');
} else if (!error.message.includes('未授权') && !error.message.includes('权限不足')) {
showNotification('导出失败,请稍后重试', 'error');
}
2025-11-17 12:56:43 +08:00
})
.finally(() => {
// 恢复按钮状态
submitBtn.disabled = false;
submitText.textContent = '导出卡密';
});
}
</script>
{% endblock %}