Kamixitong/app/web/templates/license/export.html
2025-11-28 15:56:33 +08:00

242 lines
9.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% 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 = '导出中...';
showLoading();
// 构建API URL复用base.html中的URL构建逻辑
let apiUrl = '/api/v1/licenses/export';
const frontendDomain = window.FRONTEND_DOMAIN || '';
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, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
credentials: 'same-origin',
body: JSON.stringify(formData)
})
.then(response => {
hideLoading();
// 检查响应状态
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 || '权限不足'}`);
}).catch(() => {
showNotification('权限不足,无法执行此操作', 'error');
throw new Error('403: 权限不足');
});
} else {
// 尝试解析错误信息
return response.json().then(errorData => {
showNotification(errorData.message || `导出失败: ${response.statusText}`, 'error');
throw new Error(`${response.status}: ${errorData.message || response.statusText}`);
}).catch(() => {
showNotification(`导出失败: ${response.statusText}`, 'error');
throw new Error(`${response.status}: ${response.statusText}`);
});
}
}
// 成功响应,处理文件下载
// 获取文件名
const contentDisposition = response.headers.get('Content-Disposition');
let filename = 'licenses.xlsx';
if (contentDisposition) {
const filenameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
if (filenameMatch && filenameMatch[1]) {
filename = filenameMatch[1].replace(/['"]/g, '');
// 处理URL编码的文件名
try {
filename = decodeURIComponent(filename);
} catch (e) {
// 如果解码失败,使用原始文件名
}
}
}
// 下载文件
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);
// 如果错误消息不是我们自定义的,显示通用错误消息
if (error.message && !error.message.includes(':')) {
showNotification('导出失败: ' + error.message, 'error');
} else if (!error.message.includes('未授权') && !error.message.includes('权限不足')) {
showNotification('导出失败,请稍后重试', 'error');
}
})
.finally(() => {
// 恢复按钮状态
submitBtn.disabled = false;
submitText.textContent = '导出卡密';
});
}
</script>
{% endblock %}