chore: 重写初始提交(清空历史,整理后全量提交)

This commit is contained in:
ywxapp
2026-08-16 16:54:14 +08:00
commit 6c1a106bc1
1808 changed files with 238144 additions and 0 deletions
+259
View File
@@ -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', {}); // 输出模块接口
});