2025-11-11 21:39:12 +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="generate-form">
|
|
|
|
|
|
<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_type" class="form-label">卡密类型 *</label>
|
|
|
|
|
|
<select class="form-select" id="license_type" name="license_type" required>
|
|
|
|
|
|
<option value="1">正式卡密</option>
|
|
|
|
|
|
<option value="0">试用卡密</option>
|
|
|
|
|
|
</select>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="quantity" class="form-label">生成数量 *</label>
|
|
|
|
|
|
<input type="number" class="form-control" id="quantity" name="quantity" min="1" max="1000" value="1" required>
|
|
|
|
|
|
<div class="form-text">单次最多生成1000个卡密</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" value="365">
|
|
|
|
|
|
<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-key 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>试用卡密会自动添加TRIAL_前缀</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('generate-form').addEventListener('submit', function(e) {
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
generateLicenses();
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 生成卡密
|
|
|
|
|
|
function generateLicenses() {
|
|
|
|
|
|
const submitBtn = document.getElementById('submit-btn');
|
|
|
|
|
|
const submitText = document.getElementById('submit-text');
|
|
|
|
|
|
|
|
|
|
|
|
// 获取表单数据
|
|
|
|
|
|
const formData = {
|
|
|
|
|
|
product_id: document.getElementById('product_id').value,
|
|
|
|
|
|
type: parseInt(document.getElementById('license_type').value),
|
|
|
|
|
|
count: parseInt(document.getElementById('quantity').value),
|
2025-11-12 09:19:32 +08:00
|
|
|
|
valid_days: document.getElementById('expire_days').value ? parseInt(document.getElementById('expire_days').value) : null,
|
2025-11-11 21:39:12 +08:00
|
|
|
|
prefix: '',
|
|
|
|
|
|
length: 32
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-11-12 09:19:32 +08:00
|
|
|
|
// 如果valid_days为null,删除该属性
|
|
|
|
|
|
if (formData.valid_days === null) {
|
|
|
|
|
|
delete formData.valid_days;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-11 21:39:12 +08:00
|
|
|
|
// 基础验证
|
|
|
|
|
|
if (!formData.product_id) {
|
|
|
|
|
|
showNotification('请选择产品', 'warning');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (formData.count < 1 || formData.count > 10000) {
|
|
|
|
|
|
showNotification('生成数量必须在1-10000之间', 'warning');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (formData.valid_days && (formData.valid_days < 1 || formData.valid_days > 3650)) {
|
|
|
|
|
|
showNotification('有效期必须在1-3650天之间', 'warning');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 显示加载状态
|
|
|
|
|
|
submitBtn.disabled = true;
|
|
|
|
|
|
submitText.textContent = '生成中...';
|
|
|
|
|
|
|
|
|
|
|
|
// 发送请求
|
|
|
|
|
|
apiRequest('/api/v1/licenses', {
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
body: JSON.stringify(formData)
|
|
|
|
|
|
})
|
|
|
|
|
|
.then(data => {
|
|
|
|
|
|
if (data.success) {
|
|
|
|
|
|
showNotification(`成功生成 ${data.data.count} 个卡密`, 'success');
|
|
|
|
|
|
// 延迟跳转到卡密列表
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
window.location.href = '/licenses';
|
|
|
|
|
|
}, 1500);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
showNotification(data.message || '生成失败', 'error');
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(error => {
|
|
|
|
|
|
console.error('Failed to generate licenses:', error);
|
|
|
|
|
|
showNotification('网络错误,请稍后重试', 'error');
|
|
|
|
|
|
})
|
|
|
|
|
|
.finally(() => {
|
|
|
|
|
|
// 恢复按钮状态
|
|
|
|
|
|
submitBtn.disabled = false;
|
|
|
|
|
|
submitText.textContent = '生成卡密';
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
{% endblock %}
|