Files
cursoradminapiformjifengqiang/app/manager/view/package_auth/index.html
2025-02-10 10:39:00 +08:00

786 lines
26 KiB
PHP

{extend name="../../admin/view/main"}
{block name='content'}
<style>
/* 基础样式 */
.layui-card-body {
padding: 15px;
}
.layui-table-tool {
background-color: #f8f8f8;
}
.layui-table-page {
background-color: #f8f8f8;
}
.layui-table-box {
background: #fff;
border-radius: 2px;
box-shadow: 0 1px 2px rgba(0,0,0,.1);
}
/* 时间选择器样式 */
#dateRange {
width: 280px;
}
.layui-inline .layui-input {
height: 32px;
line-height: 32px;
}
.layui-inline .layui-btn {
height: 32px;
line-height: 32px;
}
</style>
<!-- 在主容器前添加操作指南 -->
<div class="think-box-shadow" style="margin-bottom: 15px; padding: 15px;">
<h3 class="layui-inline" style="margin-right: 15px;">操作指南</h3>
<button class="layui-btn layui-btn-sm" id="showGuide">展开/收起</button>
<div class="guide-content layui-hide" style="margin-top: 10px;">
<div class="layui-card">
<div class="layui-card-body">
<div class="layui-elem-quote" style="border-left: 5px solid #009688;">
<h4>基本说明:</h4>
<p>本页面用于管理不同管理员的包名权限,可以进行查看、添加、移除等操作。</p>
</div>
<div class="layui-elem-quote" style="border-left: 5px solid #FFB800;">
<h4>操作步骤:</h4>
<ol>
<li>左侧列表显示所有可配置权限的管理员</li>
<li>绿色标签表示已授权包名数量,灰色表示未授权</li>
<li>点击【查看权限】可以查看和修改该管理员的包名权限</li>
<li>击【批量授权】可以同时给多个管理员授权相同的包名</li>
<li>点击【清空权限】可以清除选中管理员的所有包名权限</li>
</ol>
</div>
<div class="layui-elem-quote" style="border-left: 5px solid #FF5722;">
<h4>权限配置窗口说明:</h4>
<ol>
<li>左侧显示已授权的包名列表,可以搜索和移除</li>
<li>右侧显示可授权的包名列表,仅显示启用状态的包名</li>
<li>在右侧勾选包名后点击【保存配置】即可添加授权</li>
<li>两侧都支持搜索功能,可以快速查找包名</li>
<li>所有操作都会实时更新显示结果</li>
</ol>
</div>
<div class="layui-elem-quote" style="border-left: 5px solid #01AAED;">
<h4>注意事项:</h4>
<ol>
<li>批量授权会覆盖已有的权限配置,请谨慎操作</li>
<li>清空权限操作不可恢复,请确认后再操作</li>
<li>建议先使用搜索功能查找包名,再进行授权作</li>
<li>可以使用全选功能快速选择多个管理员或包名</li>
<li>如有疑问请联系技术支持</li>
</ol>
</div>
</div>
</div>
</div>
</div>
<div class="think-box-shadow main-container">
<div class="layui-row layui-col-space15">
<!-- 左侧管理员列表 -->
<div class="layui-col-md3">
<div class="layui-card">
<div class="layui-card-header">
管理员列表
<div class="layui-layout-right" style="margin:5px;">
<span class="layui-badge layui-bg-blue" style="padding: 5px 10px;"> {$users|count} </span>
</div>
</div>
<div class="layui-card-body user-list-container">
<form class="layui-form" lay-filter="userForm">
<!-- 添加搜索框 -->
<div class="search-box">
<div class="layui-form-item" style="margin-bottom: 10px;">
<div class="layui-input-block" style="margin-left: 0;">
<input type="text" id="searchUsers" placeholder="输入管理员名称搜索" class="layui-input">
</div>
</div>
</div>
<!-- 全选复选框 -->
<div class="layui-form-item" style="padding: 10px;">
<input type="checkbox" lay-filter="checkAllUsers" title="全选" lay-skin="primary" lay-tips="选中/取消选中所有管理员">
</div>
<!-- 管理员列表 -->
<div class="user-list">
{foreach $users as $user}
<div class="layui-form-item">
<input type="checkbox" name="user_ids[]" value="{$user.id}" title="{$user.username}" lay-skin="primary">
{if isset($authMap[$user.id])}
<span class="layui-badge layui-bg-green" style="margin-left:10px; padding: 4px 8px;">已授权 {$authMap[$user.id]|count} 个包名</span>
<a class="layui-btn layui-btn-normal layui-btn-sm" data-user="{$user.id}" lay-event="showAuth" style="margin-left:5px;" lay-tips="点击查看和修改该管理员的包名权限配置">
<i class="layui-icon layui-icon-edit"></i> 查看权限
</a>
{else}
<span class="layui-badge layui-bg-gray" style="margin-left:10px; padding: 4px 8px;">未授权</span>
<a class="layui-btn layui-btn-warm layui-btn-sm" data-user="{$user.id}" lay-event="showAuth" style="margin-left:5px;" lay-tips="点击为该管理员添加包名权限">
<i class="layui-icon layui-icon-add-1"></i> 添加权限
</a>
{/if}
</div>
{/foreach}
</div>
</form>
</div>
</div>
</div>
<!-- 右侧包名列表 -->
<div class="layui-col-md9">
<div class="layui-card">
<div class="layui-card-header">
包名权限配置
<div class="layui-layout-right header-btns">
<button class="layui-btn layui-btn-normal" lay-submit lay-filter="batchAuth" lay-tips="选中管理员和包名后,点击此处进行批量授权操作">
<i class="layui-icon layui-icon-add-circle"></i> 批量授权
</button>
<button class="layui-btn layui-btn-danger" id="clearAuth" lay-tips="清空选中管理员的所有包名权限,请谨慎操作">
<i class="layui-icon layui-icon-delete"></i> 清空权限
</button>
</div>
</div>
<div class="layui-card-body">
<!-- 搜索框 -->
<div class="layui-form-item" style="margin-bottom: 10px;">
<div class="layui-inline" style="width: 250px;">
<input type="text" id="searchPackages" placeholder="输入包名或应用名称搜索" class="layui-input">
</div>
<div class="layui-inline">
<input type="text" id="dateRange" placeholder="选择时间范围" class="layui-input" readonly lay-tips="选择时间范围进行筛选">
</div>
<div class="layui-inline">
<button class="layui-btn layui-btn-primary" id="resetFilter" lay-tips="清空所有筛选条件">重置</button>
</div>
</div>
<!-- 表格 -->
<table id="packageTable" lay-filter="packageTable"></table>
</div>
</div>
</div>
</div>
</div>
<!-- 修改权限详情模板引用 -->
<script type="text/html" id="authDetailTpl">
{include file="package_auth/auth_detail"}
</script>
<!-- JavaScript 部分 -->
<script>
// 全局配置
var CONFIG = {
pageSize: 10,
loadingTime: 1000,
debounceDelay: 300
};
// 消息提示
var MSG = {
networkError: '网络错误,请稍后重试!',
selectAdmin: '请选择管理员',
selectPackage: '请选择包名',
confirmClear: '确定要清空权限吗?此操作不可恢复!',
confirmBatchAuth: '确定要批量授权吗?<br>此操作将覆盖已有权限!',
getUserFailed: '获取用户信息失败',
authSuccess: '授权成功!',
clearSuccess: '清空成功!'
};
// 防抖函数
function debounce(fn, delay) {
let timer = null;
return function() {
let context = this, args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
};
}
// 成功提示
function showSuccess(msg, callback) {
layer.msg(msg, {
icon: 1,
time: CONFIG.loadingTime,
shade: 0.3
}, callback);
}
// 错误提示
function showError(msg) {
layer.msg(msg, {
icon: 2,
time: 2000,
shade: 0.3
});
}
// 表格事件处理对象
var TableEventHandler = {
// 工具条事件
tool: function(obj, callback) {
var event = obj.event;
var handlers = {
remove: function() {
layer.confirm('确定要移除此包名权限吗?', {
title: '操作确认',
btn: ['确定', '取消']
}, function(index) {
callback && callback(obj, index);
});
}
};
handlers[event] && handlers[event]();
},
// 表头工具栏事件
toolbar: function(obj, callback) {
var event = obj.event;
var handlers = {
batchRemove: function() {
var checkStatus = table.checkStatus(obj.config.id);
if (!checkStatus.data.length) {
layer.msg('请选择要移除的包名', {icon: 2});
return;
}
layer.confirm('确定要移除选中的 ' + checkStatus.data.length + ' 个包名权限吗?', {
title: '批量移除确认',
btn: ['确定', '取消']
}, function(index) {
callback && callback(checkStatus.data, index);
});
}
};
handlers[event] && handlers[event]();
}
};
// 表格缓存对象
var TableCache = {
data: {},
set: function(key, value) {
this.data[key] = value;
// 最多缓存100条数据
var keys = Object.keys(this.data);
if (keys.length > 100) {
delete this.data[keys[0]];
}
},
get: function(key) {
return this.data[key];
},
clear: function() {
this.data = {};
}
};
// 基础表格配置
var baseTableConfig = {
page: true,
limit: 15,
loading: true,
text: {
none: '暂无数据'
},
size: 'sm'
};
layui.use(['table', 'form', 'laydate'], function() {
let table = layui.table,
form = layui.form,
laydate = layui.laydate;
// 将 table 绑定到全局,以便其他函数使用
window.packageAuthTable = table;
// 初始化时间选择器
laydate.render({
elem: '#dateRange',
type: 'datetime',
range: true,
trigger: 'click',
done: function(value, date){
if(value) {
var dates = value.split(' - ');
table.reload('packageTable', {
where: {
start_time: dates[0],
end_time: dates[1]
},
page: {curr: 1}
});
}
}
});
// 重置筛选
$('#resetFilter').on('click', function(){
$('#searchPackages').val('');
$('#dateRange').val('');
table.reload('packageTable', {
where: {
keyword: '',
start_time: '',
end_time: ''
},
page: {curr: 1}
});
});
// 优化搜索功能
$('#searchPackages').on('input', debounce(function(){
var value = this.value;
var dateRange = $('#dateRange').val();
var dates = dateRange ? dateRange.split(' - ') : ['', ''];
table.reload('packageTable', {
where: {
keyword: value,
start_time: dates[0],
end_time: dates[1]
},
page: {curr: 1}
});
}, 300));
// 初始化包名权限配置表格
table.render({
elem: '#packageTable',
url: '{:url("getPackageList")}',
method: 'post',
toolbar: true,
defaultToolbar: ['filter', 'exports'],
cols: [[
{type: 'checkbox', width: 50},
{field: 'package_name', title: '包名', sort: true},
{field: 'name', title: '应用名称'}
]],
page: true,
limit: 20,
limits: [10, 20, 50, 100],
height: 'full-120',
text: {
none: '暂无包名数据'
},
size: 'sm'
});
// 管理员全选
form.on('checkbox(checkAllUsers)', function(data){
var checked = data.elem.checked;
$('input[name="user_ids[]"]').prop('checked', checked);
form.render('checkbox');
});
// 启用包名全选
form.on('checkbox(checkAllEnabled)', function(data){
var checked = data.elem.checked;
$(data.elem).closest('.layui-form-item').nextUntil('.layui-form-item:has(label:contains("禁用包名"))')
.find('input[type="checkbox"]').prop('checked', checked);
form.render('checkbox');
});
// 禁用包全选
form.on('checkbox(checkAllDisabled)', function(data){
var checked = data.elem.checked;
$(data.elem).closest('.layui-form-item').nextAll()
.find('input[type="checkbox"]').prop('checked', checked);
form.render('checkbox');
});
// 批量授权按钮事件
form.on('submit(batchAuth)', function(data) {
let userIds = [];
$('input[name="user_ids[]"]:checked').each(function() {
userIds.push($(this).val());
});
if(userIds.length === 0) {
layer.msg('请选择要授权的管理员', {icon: 2});
return false;
}
// 使用全局的 table 变量
let checkStatus = window.packageAuthTable.checkStatus('packageTable');
let packageIds = checkStatus.data.map(item => item.id);
if(packageIds.length === 0) {
layer.msg('请选择要授权的包名', {icon: 2});
return false;
}
layer.confirm('确定要批量授权吗?<br>此操作将覆盖已有权限!', {
title: '操作确认',
btn: ['确定', '取消'],
icon: 3
}, function(index) {
let loadIndex = layer.load(2);
$.ajax({
url: '{:url("batchAuth")}',
type: 'post',
data: {
user_ids: userIds,
package_ids: packageIds
},
success: function(res) {
layer.close(loadIndex);
if(res.code === 1) {
layer.msg(res.info, {icon: 1, time: 1000}, function() {
location.reload();
});
} else {
layer.msg(res.info, {icon: 2, time: 2000});
}
layer.close(index);
}
});
});
return false;
});
// 清空权限按钮事件
$('#clearAuth').click(function() {
let userIds = [];
$('input[name="user_ids[]"]:checked').each(function() {
userIds.push($(this).val());
});
if(userIds.length === 0) {
layer.msg('请选择要清空权限的管理员', {icon: 2});
return false;
}
layer.confirm('确定要清空所选管理员的权限吗?<br>此操作不可恢复!', {
title: '危险操作',
btn: ['确定清空', '取消'],
icon: 2
}, function(index) {
let loadIndex = layer.load(2);
$.ajax({
url: '{:url("clearAuth")}',
type: 'post',
data: {
user_ids: userIds
},
success: function(res) {
layer.close(loadIndex);
if(res.code === 1) {
layer.msg(res.info, {icon: 1, time: 1000}, function() {
location.reload();
});
} else {
layer.msg(res.info, {icon: 2, time: 2000});
}
layer.close(index);
}
});
});
});
// 操作指南展开/收起
$('#showGuide').click(function(){
var $content = $('.guide-content');
if ($content.hasClass('layui-hide')) {
$content.removeClass('layui-hide').hide().slideDown();
// 存储状态到 localStorage
localStorage.setItem('packageAuthGuideShow', '1');
} else {
$content.slideUp(function(){
$(this).addClass('layui-hide');
});
// 存储状态到 localStorage
localStorage.setItem('packageAuthGuideShow', '0');
}
});
// 页面加载时检查是否需要显示操作指南
if (localStorage.getItem('packageAuthGuideShow') === '1') {
$('.guide-content').removeClass('layui-hide');
}
// 初始化按钮提示
$('[lay-tips]').each(function(){
var tips = $(this).attr('lay-tips');
if(tips) {
layui.use('layer', function(){
var layer = layui.layer;
$(this).on('mouseenter', function(){
this.index = layer.tips(tips, this, {
tips: [1, '#3595CC'],
time: 0
});
}).on('mouseleave', function(){
layer.close(this.index);
});
}.bind(this));
}
});
});
// 辅助函数
function viewAuth(userId, username){
$('[data-user="' + userId + '"][lay-event="showAuth"]').click();
}
function clearSingleAuth(userId){
layer.confirm('确定要清空此管理员的权限吗?', {
title: '操作确认',
btn: ['确定', '取消'],
icon: 3,
skin: 'layui-layer-molv'
}, function(index){
var loadIndex = layer.load(2);
$.ajax({
url: '{:url("clearAuth")}',
type: 'post',
data: {
user_ids: [userId]
},
success: function(res){
layer.close(loadIndex);
if(res.code === 1){
layer.msg(res.info, {icon: 1, time: 1000}, function(){
location.reload();
});
} else {
layer.msg(res.info, {icon: 2, time: 2000});
}
layer.close(index);
}
});
});
}
// 将权限详情相关的函数抽取出来
function showAuthDetail(userId, username) {
layer.open({
type: 1,
title: username + ' 的权限配置',
area: ['1200px', '80%'],
offset: '50px',
moveType: 1,
content: $('#authDetailTpl').html(),
success: function(layero) {
window.initAuthDetailTables(userId);
// 隐藏默认的关闭按钮
$(layero).find('.layui-layer-setwin').css({
'display': 'none'
});
}
});
}
// 绑定查看权限按钮事件
$(document).on('click', '[lay-event="showAuth"]', function() {
let userId = $(this).data('user');
let username = $(this).closest('.layui-form-item').find('input[type="checkbox"]').attr('title');
showAuthDetail(userId, username);
});
</script>
<!-- 添加一些样式 -->
<style>
.guide-content ol {
padding-left: 20px;
margin: 10px 0;
}
.guide-content ol li {
line-height: 28px;
color: #666;
}
.guide-content h4 {
margin: 5px 0;
color: #333;
}
.layui-elem-quote {
margin-bottom: 10px;
}
.context-menu-layer {
box-shadow: 0 2px 8px rgba(0,0,0,.1);
background: none;
}
.context-menu {
background: #fff;
border-radius: 2px;
padding: 5px 0;
}
.context-menu .menu-item {
padding: 8px 15px;
cursor: pointer;
font-size: 14px;
color: #666;
transition: all .2s;
}
.context-menu .menu-item:hover {
background: #f2f2f2;
color: #009688;
}
.context-menu .menu-item .layui-icon {
margin-right: 5px;
font-size: 14px;
}
.context-menu .menu-item[onclick*="clearSingleAuth"] {
color: #FF5722;
}
.context-menu .menu-item[onclick*="clearSingleAuth"]:hover {
background: #fff1f0;
}
/* 管理员列表样式优化 */
.user-list .layui-form-item {
padding: 8px 0;
margin-bottom: 5px;
border-bottom: 1px solid #f0f0f0;
}
.user-list .layui-form-item:last-child {
border-bottom: none;
}
.user-list .layui-btn-sm {
height: 28px;
line-height: 28px;
padding: 0 12px;
}
.user-list .layui-badge {
font-size: 12px;
font-weight: normal;
}
.user-list .layui-btn-normal {
background-color: #1E9FFF;
}
.user-list .layui-btn-warm {
background-color: #FFB800;
}
.user-list .layui-icon {
font-size: 14px;
margin-right: 3px;
}
/* 美化搜索框 */
.search-box .layui-input {
height: 36px;
line-height: 36px;
border-radius: 2px;
}
/* 美化全选框 */
.layui-form-item .layui-form-checkbox[lay-skin=primary] {
margin-top: 0;
}
/* 右侧顶部按钮样式优化 */
.header-btns {
margin: 3px 0;
padding-right: 5px;
}
.header-btns .layui-btn {
height: 34px;
line-height: 34px;
padding: 0 15px;
font-size: 13px;
margin-left: 8px;
}
.header-btns .layui-btn .layui-icon {
font-size: 14px;
margin-right: 3px;
}
.header-btns .layui-btn-normal {
background-color: #1E9FFF;
}
.header-btns .layui-btn-normal:hover {
background-color: #0d8aff;
}
.header-btns .layui-btn-danger {
background-color: #FF5722;
}
.header-btns .layui-btn-danger:hover {
background-color: #ff4208;
}
/* 提示框样式优化 */
.layui-layer-tips {
font-size: 13px !important;
}
.layui-layer-tips .layui-layer-content {
padding: 8px 12px !important;
line-height: 1.5 !important;
border-radius: 2px !important;
}
.layui-layer-tips i.layui-layer-TipsT {
border-right-color: #3595CC !important;
}
/* 危险操作弹窗样式 */
.layer-danger .layui-layer-title {
background-color: #FF5722 !important;
color: #fff !important;
}
.layer-danger .layui-layer-btn0 {
background-color: #FF5722 !important;
border-color: #FF5722 !important;
}
/* 工具栏按钮样式 */
.auth-table-container .layui-table-tool .layui-btn {
margin-right: 8px;
}
.auth-table-container .layui-table-tool .layui-btn:last-child {
margin-right: 0;
}
.auth-table-container .layui-table-tool .layui-btn-danger:hover {
background-color: #ff4208;
}
/* 正常操作弹窗样式 */
.layer-normal .layui-layer-title {
background-color: #1E9FFF !important;
color: #fff !important;
}
.layer-normal .layui-layer-btn0 {
background-color: #1E9FFF !important;
border-color: #1E9FFF !important;
}
/* 工具栏按钮样式补充 */
.auth-table-container .layui-table-tool .layui-btn-normal {
background-color: #1E9FFF;
}
.auth-table-container .layui-table-tool .layui-btn-normal:hover {
background-color: #0d8aff;
}
</style>
{/block}