chore: 重写初始提交(清空历史,整理后全量提交)
This commit is contained in:
@@ -0,0 +1,259 @@
|
||||
layui.define(['http', 'setter', 'auth', 'upload', 'form', 'layer', 'table'], function (exports) {
|
||||
var table = layui.table, form = layui.form, layer = layui.layer, $ = layui.$, upload = layui.upload, http = layui.http
|
||||
, auth = layui.auth;
|
||||
var _savedPerms = (layui.data('backend').permission) || [];
|
||||
auth.init(_savedPerms);
|
||||
auth.setController('addon');
|
||||
var ADDON_DEV = window.ADDON_DEV || 0;
|
||||
|
||||
// 清空后台侧栏菜单的本地缓存(Layui data 存储于 setter.appName 下,键为 'menus')。
|
||||
// 插件卸载/安装/启停会改变 admin_power 菜单,必须清掉缓存让侧栏重新向后端拉取,
|
||||
// 否则侧栏会一直显示(或一直缺)已变更插件的菜单。
|
||||
function clearMenuCache() {
|
||||
var appName = (layui.setter && layui.setter.appName) || 'backend';
|
||||
layui.data(appName, { key: 'menus', remove: true });
|
||||
// 兼容旧键名(历史版本曾写入 'menu')
|
||||
layui.data(appName, { key: 'menu', remove: true });
|
||||
}
|
||||
// ===== 渲染核心表格 =====
|
||||
var { access_token, refresh_token } = layui.setter.getTokens();
|
||||
table.render({
|
||||
elem: '#dataTable'
|
||||
, url: "index" // 此处应填写你真实的后端接口地址
|
||||
, cols: [[
|
||||
{ field: 'title', title: '插件名称', minWidth: 180 },
|
||||
{ field: 'name', title: '标识', width: 120 },
|
||||
{ field: 'author', title: '开发者', width: 120 }
|
||||
, { field: 'version', title: '版本号', width: 100, align: 'center' }
|
||||
, { field: 'description', title: '功能描述', minWidth: 250 }
|
||||
, { field: 'status', title: '运行状态', width: 110, align: 'center', templet: '#switchTpl' } // 绑定开关模板
|
||||
, { fixed: 'right', title: '操作', toolbar: '#operateTpl', width: 300, align: 'right' } // 绑定操作栏模板
|
||||
]]
|
||||
, page: true // 开启分页
|
||||
, limit: 10
|
||||
, limits: [10, 20, 50]
|
||||
, skin: 'line' // 设定表格风格为行边框风格
|
||||
, response: {
|
||||
statusName: 'code' // 状态码字段
|
||||
, statusCode: 0 // 成功状态码
|
||||
, msgName: 'message' // 提示信息字段(后端返回 message)
|
||||
, countName: 'count' // 数据总数字段
|
||||
, dataName: 'data' // 数据列表字段
|
||||
}
|
||||
, done: function (res, curr, count) {
|
||||
var view = $('#dataTable').next('.layui-table-view');
|
||||
view.find('[data-perm]').each(function () {
|
||||
var perm = $(this).attr('data-perm');
|
||||
if (perm && !auth.has(perm)) { $(this).remove(); }
|
||||
});
|
||||
$('.layui-btn[data-perm]').each(function () {
|
||||
var perm = $(this).attr('data-perm');
|
||||
if (perm && !auth.has(perm)) { $(this).remove(); }
|
||||
});
|
||||
// 开发模式关闭时隐藏操作列的「设计」按钮
|
||||
// if (!ADDON_DEV) { $('.dev-design').remove(); }
|
||||
}
|
||||
});
|
||||
|
||||
// ===== 事件绑定(提前到这里:即便下方 upload/form 初始化出错,行内按钮依然可用) =====
|
||||
table.on('toolbar(dataTable)', function (elem) {
|
||||
switch (elem.event) {
|
||||
case 'dataCreate':
|
||||
active.dataCreate({ pid: 0, type: 1 });
|
||||
break;
|
||||
case 'dataRecybin':
|
||||
active.dataRecybin();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
table.on('tool(dataTable)', function (elem) {
|
||||
var data = elem.data;
|
||||
// 插件标识:优先用 name,缺失时回退到 id(后端 index 两种都返回)
|
||||
var addonName = data.name || data.id || '';
|
||||
switch (elem.event) {
|
||||
case 'update':
|
||||
active.dataEdit(data);
|
||||
break;
|
||||
case 'config':
|
||||
if (!addonName) { layer.msg('缺少插件标识', { icon: 2 }); break; }
|
||||
location.href = 'setting?addon=' + encodeURIComponent(addonName);
|
||||
break;
|
||||
case 'uninstall':
|
||||
if (!addonName) { layer.msg('缺少插件标识', { icon: 2 }); break; }
|
||||
active.uninstall(addonName);
|
||||
break;
|
||||
case 'more':
|
||||
var that = this;
|
||||
var dropdown = layui.dropdown;
|
||||
// 水平对齐方式
|
||||
dropdown.render({
|
||||
elem: that,
|
||||
align: 'center', // align 已配置在元素 `lay-options` 属性上
|
||||
show: true,accordion : true,
|
||||
data: [{
|
||||
title: '设计',
|
||||
id: 'design'
|
||||
}, {
|
||||
title: '打包',
|
||||
id: 'pack'
|
||||
}, {
|
||||
title: '发布',
|
||||
id: 'submitOfficial'
|
||||
}],
|
||||
click: function (data, othis) {
|
||||
switch (data.id) {
|
||||
case 'pack':
|
||||
// 触发后端 addon::pack 下载该插件的 zip 包(addon/temp/<name>-<version>.zip)
|
||||
if (!addonName) { layer.msg('缺少插件标识', { icon: 2 }); break; }
|
||||
window.location.href = 'pack?name=' + encodeURIComponent(addonName);
|
||||
break;
|
||||
case 'design':
|
||||
if (!addonName) { layer.msg('缺少插件标识', { icon: 2 }); break; }
|
||||
location.href = 'design?addon=' + encodeURIComponent(addonName);
|
||||
break;
|
||||
case 'submitOfficial':
|
||||
// 发布到官方市场:打包本机已装插件并 POST 到官方提交接口,进入待审核
|
||||
if (!addonName) { layer.msg('缺少插件标识', { icon: 2 }); break; }
|
||||
layer.confirm('确定将「' + (data.title || addonName) + '」发布到官方市场吗?\n提交后需官方审核通过才公开上架。', function (index) {
|
||||
layer.close(index);
|
||||
var loadIdx = layer.load(1, { shade: [0.3, '#fff'] });
|
||||
http.post('submitOfficial', { name: addonName })
|
||||
.then(function (res) {
|
||||
layer.close(loadIdx);
|
||||
if (res.code === 0) {
|
||||
layer.msg(res.message || '已提交,等待官方审核', { icon: 1 });
|
||||
} else {
|
||||
layer.msg(res.message || res.msg || '提交失败', { icon: 2 });
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
layer.close(loadIdx);
|
||||
layer.msg('请求失败', { icon: 2 });
|
||||
});
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
break;
|
||||
case 'default':
|
||||
console.warn('未处理的操作事件:', elem.event, data);
|
||||
}
|
||||
});
|
||||
|
||||
// 顶部功能按钮 + 行内操作共用
|
||||
var active = {
|
||||
uninstall: function (name) {
|
||||
layer.prompt({
|
||||
formType: 1
|
||||
, title: '敏感操作,请验证口令'
|
||||
}, function (value, index) {
|
||||
layer.close(index);
|
||||
http.delete('uninstall', { name: name })
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
layer.close(index);
|
||||
clearMenuCache(); // 插件菜单已删除,清掉侧栏菜单缓存
|
||||
location.reload(); // 重新加载整页,侧栏立即刷新
|
||||
} else {
|
||||
layer.msg(res.msg || '操作失败');
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
batchDel: function () { // 批量卸载
|
||||
var checkStatus = table.checkStatus('dataTable');
|
||||
var data = checkStatus.data;
|
||||
if (data.length === 0) {
|
||||
layer.msg('请至少选中一项进行卸载', { icon: 0 });
|
||||
return;
|
||||
}
|
||||
layer.confirm('确定要批量卸载选中的 ' + data.length + ' 个插件吗?', function (index) {
|
||||
layer.msg('正在批量卸载...', { icon: 1 });
|
||||
table.reload('dataTable');
|
||||
layer.close(index);
|
||||
});
|
||||
},
|
||||
refresh: function () { // 刷新表格
|
||||
table.reload('dataTable');
|
||||
layer.msg('已刷新列表', { icon: 1 });
|
||||
}
|
||||
};
|
||||
|
||||
$('.layui-btn').on('click', function () {
|
||||
var type = $(this).data('type');
|
||||
active[type] && active[type].call(this);
|
||||
});
|
||||
|
||||
console.log(layui.setter.getTokens());
|
||||
var inst = upload.render({
|
||||
elem: '#buttonInstall',
|
||||
field: 'file',
|
||||
url: "upload", // 上传接口地址
|
||||
accept: 'file', // 只允许上传文件
|
||||
// 注意:不要设置 acceptMime。该属性会让浏览器文件选择框按 MIME 过滤,
|
||||
// 而 zip 在本机常被识别为 application/x-zip-compressed / application/octet-stream,
|
||||
// 导致选择框中插件包被置灰、无法选中。仅用 exts 在选完后校验后缀即可。
|
||||
exts: 'zip', // 仅允许 zip 插件包(后端 AddonService 只支持 zip)
|
||||
headers: { 'Authorization': `Bearer ${access_token}` }, // 鉴权
|
||||
|
||||
done: function (res) {
|
||||
// 上传成功的回调
|
||||
if (res.code == 0) {
|
||||
layer.msg('插件安装成功!', { icon: 1 });
|
||||
clearMenuCache(); // 插件菜单已变化,清掉侧栏菜单缓存
|
||||
location.reload(); // 重新加载整页,侧栏立即刷新
|
||||
} else {
|
||||
layer.msg('安装失败: ' + res.message, { icon: 2 });
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
// 上传失败的回调
|
||||
// 当上传失败时,可在此处生成「重新上传」按钮,并执行该方法重新触发上传提交
|
||||
/*
|
||||
$('#btn').on('click', function(){
|
||||
inst.upload();
|
||||
})
|
||||
*/
|
||||
}
|
||||
});
|
||||
// ===== 监听顶部搜索表单提交 =====
|
||||
form.on('submit(searchBtn)', function (data) {
|
||||
var field = data.field; // 获取搜索表单的值
|
||||
// 重载表格,将搜索条件传给后端
|
||||
table.reload('dataTable', {
|
||||
where: field,
|
||||
page: { curr: 1 } // 搜索后回到第一页
|
||||
});
|
||||
return false; // 阻止表单默认跳转
|
||||
});
|
||||
|
||||
// ===== 监听状态开关(启用/停用)的切换 =====
|
||||
form.on('switch(statusSwitch)', function (obj) {
|
||||
var name = this.value; // value 绑定的是插件名 d.id
|
||||
var status = obj.elem.checked ? 1 : 0; // 根据开关状态赋值
|
||||
var action = status ? 'enable' : 'disable';
|
||||
var that = obj.othis;
|
||||
http.post('toggle', { name: name, action: action })
|
||||
.then(function (res) {
|
||||
if (res.code === 0) {
|
||||
layer.msg(status ? '已启用' : '已停用', { icon: 1 });
|
||||
clearMenuCache(); // 菜单可见性已变化,清掉侧栏菜单缓存(下次导航即刷新)
|
||||
} else {
|
||||
layer.msg(res.message || '操作失败', { icon: 2 });
|
||||
that.find('input').prop('checked', !status);
|
||||
form.render();
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
layer.msg('请求失败', { icon: 2 });
|
||||
that.find('input').prop('checked', !status);
|
||||
form.render();
|
||||
});
|
||||
});
|
||||
|
||||
exports('addon', {}); // 输出模块接口
|
||||
});
|
||||
Reference in New Issue
Block a user