343 lines
13 KiB
JavaScript
343 lines
13 KiB
JavaScript
layui.use(['table', 'form', 'layer'], function(){
|
|
var table = layui.table;
|
|
var form = layui.form;
|
|
var layer = layui.layer;
|
|
var $ = layui.$;
|
|
|
|
// 自定义验证规则
|
|
form.verify({
|
|
min1: function(value) {
|
|
if (value < 1) {
|
|
return '必须大于0';
|
|
}
|
|
}
|
|
});
|
|
|
|
// 初始化表格
|
|
table.render({
|
|
elem: '#license-table',
|
|
url: '/api/licenses',
|
|
headers: {
|
|
'Authorization': 'Bearer ' + localStorage.getItem('token')
|
|
},
|
|
toolbar: '#tableToolbar',
|
|
defaultToolbar: ['filter', 'exports', 'print'],
|
|
cols: [[
|
|
{type: 'checkbox'},
|
|
{field: 'code', title: '授权码', width: 320, templet: function(d){
|
|
return '<div class="layui-table-cell laytable-cell-1-code">' +
|
|
d.code +
|
|
'<a class="layui-btn layui-btn-xs layui-btn-normal" lay-event="copy" style="margin-left:5px;">复制</a>' +
|
|
'</div>';
|
|
}},
|
|
{field: 'license_type', title: '授权类型', width: 100, templet: function(d){
|
|
var types = {
|
|
'time': '时间授权',
|
|
'count': '次数授权',
|
|
'permanent': '永久授权'
|
|
};
|
|
return types[d.license_type.toLowerCase()] || d.license_type;
|
|
}},
|
|
{field: 'duration', title: '有效期', width: 150, templet: function(d){
|
|
if(d.license_type.toLowerCase() === 'time') {
|
|
let minutes = d.duration;
|
|
if (minutes >= 525600) {
|
|
return Math.floor(minutes / 525600) + '年';
|
|
} else if (minutes >= 43200) {
|
|
return Math.floor(minutes / 43200) + '月';
|
|
} else if (minutes >= 1440) {
|
|
return Math.floor(minutes / 1440) + '天';
|
|
} else if (minutes >= 60) {
|
|
return Math.floor(minutes / 60) + '小时';
|
|
} else {
|
|
return minutes + '分钟';
|
|
}
|
|
}
|
|
return '-';
|
|
}},
|
|
{field: 'max_uses', title: '使用次数', width: 100, templet: function(d){
|
|
if(d.license_type.toLowerCase() === 'count') {
|
|
return d.max_uses || 0;
|
|
}
|
|
return '-';
|
|
}},
|
|
{field: 'status', title: '状态', width: 100, templet: function(d){
|
|
var status = d.status.toLowerCase();
|
|
if(status === 'unused') return '<span class="layui-badge layui-bg-green">未使用</span>';
|
|
if(status === 'used') return '<span class="layui-badge layui-bg-gray">已使用</span>';
|
|
if(status === 'expired') return '<span class="layui-badge layui-bg-orange">已过期</span>';
|
|
if(status === 'revoked') return '<span class="layui-badge layui-bg-red">已撤销</span>';
|
|
return '<span class="layui-badge layui-bg-black">未知</span>';
|
|
}},
|
|
{field: 'used_by', title: '使用设备', width: 180},
|
|
{field: 'used_at', title: '使用时间', width: 160, templet: function(d){
|
|
return d.used_at ? new Date(d.used_at).toLocaleString() : '-';
|
|
}},
|
|
{field: 'batch_no', title: '批次号', width: 160},
|
|
{field: 'remark', title: '备注'},
|
|
{field: 'bind_count', title: '可绑定次数', width: 100, templet: function(d){
|
|
if(d.bind_count === -1) return '<span class="layui-badge layui-bg-blue">无限制</span>';
|
|
if(d.bind_count === 0) return '<span class="layui-badge layui-bg-gray">已用完</span>';
|
|
return d.bind_count;
|
|
}},
|
|
{fixed: 'right', title: '操作', toolbar: '#tableRowBar', width: 180, templet: function(d){
|
|
var btns = [
|
|
'<a class="layui-btn layui-btn-xs" lay-event="view">查看</a>',
|
|
'<a class="layui-btn layui-btn-xs layui-btn-warm" lay-event="logs">日志</a>'
|
|
];
|
|
// 只有未过期且未撤销的授权码才能撤销
|
|
if(d.status.toLowerCase() !== 'expired' && d.status.toLowerCase() !== 'revoked') {
|
|
btns.push('<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="revoke">撤销</a>');
|
|
}
|
|
return btns.join('');
|
|
}}
|
|
]],
|
|
page: true,
|
|
parseData: function(res) {
|
|
if (res.code === 401) {
|
|
window.location.href = '/login';
|
|
return;
|
|
}
|
|
return {
|
|
"code": res.code,
|
|
"msg": res.msg,
|
|
"count": res.count,
|
|
"data": res.data
|
|
};
|
|
}
|
|
});
|
|
|
|
// 表格工具栏事件
|
|
table.on('toolbar(license-table)', function(obj){
|
|
var checkStatus = table.checkStatus(obj.config.id);
|
|
|
|
switch(obj.event){
|
|
case 'refresh':
|
|
table.reload('license-table');
|
|
break;
|
|
case 'copySelected':
|
|
var data = checkStatus.data;
|
|
if(data.length === 0){
|
|
layer.msg('请选择要复制的授权码');
|
|
return;
|
|
}
|
|
|
|
// 提取授权码并按格式组织
|
|
var codes = data.map(item => item.code);
|
|
var copyText = '';
|
|
|
|
// 弹出选择框
|
|
layer.confirm('请选择复制格式', {
|
|
btn: ['换行分隔', '逗号分隔']
|
|
}, function(index){
|
|
// 换行分隔
|
|
copyText = codes.join('\n');
|
|
copyToClipboard(copyText);
|
|
layer.close(index);
|
|
}, function(index){
|
|
// 逗号分隔
|
|
copyText = codes.join(',');
|
|
copyToClipboard(copyText);
|
|
layer.close(index);
|
|
});
|
|
break;
|
|
case 'batchDel':
|
|
var data = checkStatus.data;
|
|
if(data.length === 0){
|
|
layer.msg('请选择要删除的授权码');
|
|
return;
|
|
}
|
|
layer.confirm('确定撤销选中的授权码吗?', function(index){
|
|
var codes = data.map(item => item.code);
|
|
fetch('/api/licenses/batch/revoke', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
credentials: 'include',
|
|
body: JSON.stringify({codes: codes})
|
|
})
|
|
.then(response => response.json())
|
|
.then(result => {
|
|
if(result.error) {
|
|
layer.msg(result.error);
|
|
return;
|
|
}
|
|
layer.msg('批量撤销成功');
|
|
table.reload('license-table');
|
|
})
|
|
.catch(error => {
|
|
layer.msg('批量撤销失败:' + error.message);
|
|
});
|
|
layer.close(index);
|
|
});
|
|
break;
|
|
}
|
|
});
|
|
|
|
// 添加复制到剪贴板的函数
|
|
function copyToClipboard(text) {
|
|
// 创建临时文本区域
|
|
var textarea = document.createElement('textarea');
|
|
textarea.value = text;
|
|
document.body.appendChild(textarea);
|
|
|
|
// 选择文本
|
|
textarea.select();
|
|
textarea.setSelectionRange(0, 99999); // 兼容移动设备
|
|
|
|
try {
|
|
// 执行复制
|
|
var successful = document.execCommand('copy');
|
|
if (successful) {
|
|
layer.msg('复制成功');
|
|
} else {
|
|
layer.msg('复制失败,请手动复制');
|
|
}
|
|
} catch (err) {
|
|
layer.msg('复制失败:' + err.message);
|
|
}
|
|
|
|
// 移除临时文本区域
|
|
document.body.removeChild(textarea);
|
|
}
|
|
|
|
// 行工具栏事件
|
|
table.on('tool(license-table)', function(obj){
|
|
var data = obj.data;
|
|
|
|
switch(obj.event){
|
|
case 'view':
|
|
layer.alert(JSON.stringify(data, null, 2), {
|
|
title: '授权码详情'
|
|
});
|
|
break;
|
|
case 'logs':
|
|
layer.open({
|
|
type: 2,
|
|
title: '使用日志',
|
|
area: ['800px', '600px'],
|
|
content: '/admin/license-logs?id=' + data.id + '&token=' + localStorage.getItem('token')
|
|
});
|
|
break;
|
|
case 'revoke':
|
|
layer.confirm('确定撤销该授权码吗?', function(index){
|
|
fetch('/api/licenses/' + data.code + '/revoke', {
|
|
method: 'POST',
|
|
credentials: 'include'
|
|
})
|
|
.then(response => response.json())
|
|
.then(result => {
|
|
if (result.error) {
|
|
layer.msg(result.error);
|
|
return;
|
|
}
|
|
layer.msg('撤销成功');
|
|
table.reload('license-table');
|
|
})
|
|
.catch(error => {
|
|
layer.msg('撤销失败:' + error.message);
|
|
});
|
|
layer.close(index);
|
|
});
|
|
break;
|
|
case 'copy':
|
|
copyToClipboard(data.code);
|
|
break;
|
|
}
|
|
});
|
|
|
|
// 搜索表单提交
|
|
form.on('submit(search)', function(data){
|
|
// 转换所有字段为小写
|
|
Object.keys(data.field).forEach(key => {
|
|
if(data.field[key]) {
|
|
data.field[key] = data.field[key].toLowerCase();
|
|
}
|
|
});
|
|
|
|
table.reload('license-table', {
|
|
where: data.field,
|
|
page: {
|
|
curr: 1
|
|
}
|
|
});
|
|
return false;
|
|
});
|
|
|
|
// 创建授权码按钮点击事件
|
|
$('#create-license').on('click', function(){
|
|
layer.open({
|
|
type: 1,
|
|
title: '生成授权码',
|
|
area: ['500px', '400px'],
|
|
content: $('#createLicenseTpl').html(),
|
|
success: function(){
|
|
form.render();
|
|
}
|
|
});
|
|
});
|
|
|
|
// 监听授权类型切换
|
|
form.on('select(licenseType)', function(data){
|
|
if(data.value === 'time'){
|
|
$('#durationItem').show();
|
|
$('#maxUsesItem').hide();
|
|
} else if(data.value === 'count'){
|
|
$('#durationItem').hide();
|
|
$('#maxUsesItem').show();
|
|
} else {
|
|
$('#durationItem').hide();
|
|
$('#maxUsesItem').hide();
|
|
}
|
|
});
|
|
|
|
// 创建授权码表单提交
|
|
form.on('submit(licenseSubmit)', function(data){
|
|
var field = data.field;
|
|
|
|
// 构造请求数据,确保数值类型正确
|
|
const submitData = {
|
|
license_type: field.license_type.toLowerCase(),
|
|
count: parseInt(field.count),
|
|
remark: field.remark
|
|
};
|
|
|
|
// 根据授权类型处理参数
|
|
if(field.license_type.toLowerCase() === 'time'){
|
|
submitData.duration = parseInt(field.duration) * parseInt(field.duration_unit);
|
|
delete field.max_uses;
|
|
} else if(field.license_type.toLowerCase() === 'count'){
|
|
submitData.max_uses = parseInt(field.max_uses);
|
|
delete field.duration;
|
|
} else {
|
|
delete field.duration;
|
|
delete field.max_uses;
|
|
}
|
|
|
|
fetch('/api/licenses', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': 'Bearer ' + localStorage.getItem('token')
|
|
},
|
|
credentials: 'include',
|
|
body: JSON.stringify(submitData)
|
|
})
|
|
.then(response => response.json())
|
|
.then(result => {
|
|
if (result.error) {
|
|
layer.msg(result.error);
|
|
return;
|
|
}
|
|
layer.closeAll('page');
|
|
layer.msg('授权码生成成功');
|
|
table.reload('license-table');
|
|
})
|
|
.catch(error => {
|
|
layer.msg('生成失败:' + error.message);
|
|
});
|
|
|
|
return false;
|
|
});
|
|
});
|