209 lines
8.0 KiB
HTML
209 lines
8.0 KiB
HTML
{% 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="import-form" enctype="multipart/form-data">
|
||
<div class="mb-3">
|
||
<label for="product_id" class="form-label">选择产品 *</label>
|
||
<select class="form-select" id="product_id" name="product_id" required>
|
||
<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="license_file" class="form-label">选择文件 *</label>
|
||
<input type="file" class="form-control" id="license_file" name="license_file" accept=".txt,.csv" required>
|
||
<div class="form-text">支持TXT或CSV格式文件,每行一个卡密</div>
|
||
</div>
|
||
|
||
<div class="mb-3">
|
||
<label for="license_type" class="form-label">卡密类型</label>
|
||
<select class="form-select" id="license_type" name="license_type">
|
||
<option value="">自动识别</option>
|
||
<option value="1">正式卡密</option>
|
||
<option value="0">试用卡密</option>
|
||
</select>
|
||
<div class="form-text">如果选择自动识别,系统会根据卡密前缀判断类型</div>
|
||
</div>
|
||
|
||
<div class="mb-3">
|
||
<label for="expire_days" class="form-label">有效期(天)</label>
|
||
<input type="number" class="form-control" id="expire_days" name="expire_days" min="1" max="3650">
|
||
<div class="form-text">卡密有效期天数,留空表示使用文件中的设置或永久有效</div>
|
||
</div>
|
||
|
||
<div class="mb-3">
|
||
<label for="max_devices" class="form-label">最大绑定设备数</label>
|
||
<input type="number" class="form-control" id="max_devices" name="max_devices" min="1" max="100" value="1">
|
||
<div class="form-text">同一卡密最多可绑定的设备数量</div>
|
||
</div>
|
||
|
||
<div class="mb-3">
|
||
<label for="description" class="form-label">备注</label>
|
||
<textarea class="form-control" id="description" name="description" rows="3"></textarea>
|
||
</div>
|
||
|
||
<button type="submit" class="btn btn-primary" id="submit-btn">
|
||
<i class="fas fa-file-import 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>支持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>
|
||
|
||
<h6 class="mt-3">示例文件格式</h6>
|
||
<pre class="bg-light p-2 small">LICENSE_KEY_001
|
||
LICENSE_KEY_002
|
||
TRIAL_KEY_001
|
||
TRIAL_KEY_002</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block extra_js %}
|
||
<script>
|
||
// 页面加载完成后初始化
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
initEventListeners();
|
||
});
|
||
|
||
// 初始化事件监听器
|
||
function initEventListeners() {
|
||
// 表单提交
|
||
document.getElementById('import-form').addEventListener('submit', function(e) {
|
||
e.preventDefault();
|
||
importLicenses();
|
||
});
|
||
}
|
||
|
||
// 导入卡密
|
||
function importLicenses() {
|
||
const submitBtn = document.getElementById('submit-btn');
|
||
const submitText = document.getElementById('submit-text');
|
||
const fileInput = document.getElementById('license_file');
|
||
|
||
// 获取表单数据
|
||
const formData = new FormData();
|
||
formData.append('product_id', document.getElementById('product_id').value);
|
||
formData.append('license_file', fileInput.files[0]);
|
||
|
||
const licenseType = document.getElementById('license_type').value;
|
||
if (licenseType) {
|
||
formData.append('license_type', licenseType);
|
||
}
|
||
|
||
const expireDays = document.getElementById('expire_days').value;
|
||
if (expireDays) {
|
||
formData.append('expire_days', expireDays);
|
||
}
|
||
|
||
const maxDevices = document.getElementById('max_devices').value;
|
||
if (maxDevices) {
|
||
formData.append('max_devices', maxDevices);
|
||
}
|
||
|
||
const description = document.getElementById('description').value.trim();
|
||
if (description) {
|
||
formData.append('description', description);
|
||
}
|
||
|
||
// 基础验证
|
||
if (!document.getElementById('product_id').value) {
|
||
showNotification('请选择产品', 'warning');
|
||
return;
|
||
}
|
||
|
||
if (!fileInput.files[0]) {
|
||
showNotification('请选择要导入的文件', 'warning');
|
||
return;
|
||
}
|
||
|
||
// 显示加载状态
|
||
submitBtn.disabled = true;
|
||
submitText.textContent = '导入中...';
|
||
|
||
// 发送请求
|
||
showLoading();
|
||
fetch('/api/v1/licenses/import', {
|
||
method: 'POST',
|
||
body: formData,
|
||
credentials: 'same-origin'
|
||
})
|
||
.then(response => {
|
||
hideLoading();
|
||
if (response.ok) {
|
||
return response.json();
|
||
} else {
|
||
throw new Error(`HTTP error! status: ${response.status}`);
|
||
}
|
||
})
|
||
.then(data => {
|
||
if (data.success) {
|
||
showNotification(`成功导入 ${data.data.imported} 个卡密,跳过 ${data.data.skipped} 个重复卡密`, 'success');
|
||
// 延迟跳转到卡密列表
|
||
setTimeout(() => {
|
||
window.location.href = '/licenses';
|
||
}, 2000);
|
||
} else {
|
||
showNotification(data.message || '导入失败', 'error');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
hideLoading();
|
||
console.error('Failed to import licenses:', error);
|
||
showNotification('导入失败,请检查文件格式后重试', 'error');
|
||
})
|
||
.finally(() => {
|
||
// 恢复按钮状态
|
||
submitBtn.disabled = false;
|
||
submitText.textContent = '导入卡密';
|
||
});
|
||
}
|
||
</script>
|
||
{% endblock %} |