// ==UserScript==
// @name 企业微信后台权限管理优化
// @namespace https://bbs.tampermonkey.net.cn/
// @version 0.3.0
// @description 在页面上创建一个悬浮按钮,点击后显示所有的管理员姓名和他所管理的部门
// @author 肆散的尘埃i
// @icon https://wwcdn.weixin.qq.com/node/wework/images/startPagePreview_logo.0a7763ab2f.svg
// @match http*://work.weixin.qq.com/*
// @require https://scriptcat.org/lib/637/1.4.3/ajaxHooker.js
// @require https://scriptcat.org/lib/2311/1.1.0/createFloatingButton.js
// @require https://scriptcat.org/lib/2253/1.0.1/show_message.js
// @grant none
// ==/UserScript==
(function() {
'use strict';
// 使用技术:https://bbs.tampermonkey.net.cn/forum.php?mod=viewthread&tid=3284&page=1
// 设置脚本启动时间,根据访问访问此链接的时间,适当添加 @run-at document-start
ajaxHooker.hook(request => {
// 角色列表
if (request.url.includes('/wework_admin/profile/role/getRoleList')) {
request.response = res => {
const responseText = res.response; // 注意保存原数据
// 存储
localStorage.setItem("RoleList",responseText);
console.log("已获取到数据,并且存入localStorage,名称为:RoleList")
// 创建悬浮按钮,设置名称并绑定点击事件
createFloatingButton(() => {
performing_function();
}, "显示菜单");
show_message({
message: '已获取到数据',
type: 'success',
position: 'top-right',
opacity: 0.9,
});
};
}
});
let originalTableData = []; // 保存原始数据,供重置时使用
// 创建全屏显示的 div
function createFullScreenDIV(htmlString) {
// 禁用页面滚动
document.body.style.overflow = 'hidden';
// 创建全屏遮罩层
const overlay = document.createElement('div');
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.8);
z-index: 10000;
display: flex;
justify-content: center;
align-items: center;
overflow-y: auto;
`;
// 创建内容容器
const contentContainer = document.createElement('div');
contentContainer.style.cssText = `
max-height: 80vh;
max-width: 90vw;
overflow-y: auto;
background-color: white;
padding: 20px;
border-radius: 8px;
`;
// 创建关闭按钮
const closeButton = document.createElement('div');
closeButton.innerText = '×';
closeButton.style.cssText = `
position: absolute;
top: 10px;
right: 25px;
width: 30px;
height: 30px;
background: rgba(255, 255, 255, 0.3);
color: white;
text-align: center;
line-height: 30px;
font-size: 20px;
cursor: pointer;
border-radius: 50%;
z-index: 10001;
`;
// 关闭全屏显示的函数
function closeFullScreen() {
document.body.removeChild(overlay);
document.body.style.overflow = '';
document.removeEventListener('keydown', handleKeyDown); // 移除键盘事件监听器
}
// 处理键盘事件的函数
function handleKeyDown(event) {
if (event.key === 'Escape') {
closeFullScreen();
}
}
// 添加键盘事件监听器,监听 ESC 键
document.addEventListener('keydown', handleKeyDown);
// 设置关闭按钮的点击事件
closeButton.addEventListener('click', closeFullScreen);
// 将传入的 HTML 字符串添加到内容容器中
contentContainer.appendChild(htmlString);
// 将内容容器和关闭按钮添加到遮罩层中
overlay.appendChild(contentContainer);
overlay.appendChild(closeButton);
// 将遮罩层添加到文档中
document.body.appendChild(overlay);
}
// 初始化表格,并保存原始数据
function initTable(roleList) {
const table = document.createElement('table');
table.style.cssText = `
width: 100%;
border-collapse: collapse;
background-color: white;
`;
const headerRow = document.createElement('tr');
const headers = ['序号', '管理员名称', '组织权限列表'];
headers.forEach(headerText => {
const th = document.createElement('th');
th.innerText = headerText;
th.style.cssText = `
border: 1px solid #ddd;
padding: 8px;
text-align: center;
background-color: #f2f2f2;
font-weight: bold;
`;
headerRow.appendChild(th);
});
table.appendChild(headerRow);
originalTableData = []; // 清空之前的原始数据
roleList.forEach((role, index) => {
// 创建一行
const tr = document.createElement('tr');
// 序号
const idTd = document.createElement('td');
idTd.innerText = index + 1;
idTd.style.cssText = `
width: 5%;
border: 1px solid #ddd;
padding: 8px;
text-align: center;
`;
// tr.appendChild(idTd);
// 管理员姓名
const adminNameTd = document.createElement('td');
if (role.admin_list.item.length > 0) {
const admin_list = role.admin_list.item.map(item =>
`${item.name}`
).join(', ');
adminNameTd.innerHTML = admin_list;
} else {
adminNameTd.innerText = '无管理员';
}
adminNameTd.style.cssText = `
width: 10%;
border: 1px solid #ddd;
padding: 8px;
text-align: center;
`;
// tr.appendChild(adminNameTd);
// 所管理的组织
const partyAuthTd = document.createElement('td');
const filteredPartyAuthList = role.party_auth_list.item
.filter(item => item.name !== '未加入组织的成员')
.map(item => {
const span = document.createElement('span');
span.textContent = item.name;
span.style.cssText = `
display: inline-block;
padding: 5px 10px;
background-color: #f0f0f0;
color: #333;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 14px;
line-height: 1.5;
cursor: default;
margin-right: 8px;
margin-top: 4px;
margin-bottom: 4px;
`
return span.outerHTML; // 返回 span 元素的 HTML 字符串
})
.join('');
partyAuthTd.innerHTML = filteredPartyAuthList || "超级管理员";
partyAuthTd.style.cssText = `
width: 80%;
border: 1px solid #ddd;
padding: 8px;
text-align: left;
`;
// tr.appendChild(partyAuthTd);
//TODO 统一加入到表格内,序号有些问题
// 如果“组织权限列表”不为空,则添加到表格。不显示超级管理员
if(filteredPartyAuthList.length > 0){
tr.appendChild(idTd);
tr.appendChild(adminNameTd);
tr.appendChild(partyAuthTd);
}
originalTableData.push(tr.cloneNode(true)); // 保存每行的初始状态
table.appendChild(tr);
});
return table;
}
// 搜索函数,只处理组织权限列表搜索,并高亮匹配到的部分
function searchTable(partyAuthSearch) {
// 获取表格
const table = document.querySelector('table');
// 保存表格的原始宽度
const originalWidth = table.offsetWidth;
// 获取所有的表格行
const tableRows = document.querySelectorAll('table tr');
tableRows.forEach(row => {
// 查找每一行的第三个单元格(假设包含组织权限信息)
const partyAuthCell = row.querySelector('td:nth-child(3)');
if (partyAuthCell) {
// 获取组织权限文本并转换为小写,方便搜索
const partyAuthText = partyAuthCell.innerHTML.toLowerCase();
const searchTerm = partyAuthSearch.toLowerCase();
// 恢复所有标签的样式
const spans = Array.from(partyAuthCell.getElementsByTagName('span'));
spans.forEach(span => {
const spanText = span.textContent.toLowerCase();
if (spanText.includes(searchTerm)) {
// 高亮匹配的标签
span.style.backgroundColor = 'yellow';
span.style.fontWeight = 'bold';
} else {
// 恢复未匹配的标签样式
span.style.backgroundColor = '#f0f0f0';
span.style.color = '#333';
span.style.border = '1px solid #ccc';
span.style.fontWeight = 'normal';
}
});
if (partyAuthText.includes(searchTerm)) {
// 如果匹配,显示这一行
row.style.display = '';
} else {
// 如果不匹配,隐藏这一行
row.style.display = 'none';
}
}
});
// 恢复表格的宽度
table.style.width = `${originalWidth}px`;
}
// 定义重置表格的函数
function resetTable(partyAuthInput, tableRows) {
// 清空搜索框的输入内容
if (partyAuthInput) {
partyAuthInput.value = '';
}
// 显示所有的表格行
tableRows.forEach(row => {
// 显示每一行
row.style.display = '';
// 恢复每一行中标签的样式
const spans = Array.from(row.getElementsByTagName('span'));
spans.forEach(span => {
span.style.backgroundColor = '#f0f0f0';
span.style.color = '#333';
span.style.border = '1px solid #ccc';
span.style.fontWeight = 'normal';
});
});
}
// 创建搜索栏容器
function createSearchContainer(tableRows) {
const searchContainer = document.createElement('div');
searchContainer.style.cssText = `
margin-bottom: 20px; /* 增加底部间距 */
display: flex;
justify-content: flex-start; /* 左对齐容器内元素 */
align-items: center; /* 垂直居中对齐 */
gap: 15px; /* 增加元素之间的间距 */
padding: 10px; /* 增加内边距 */
background-color: #f9f9f9; /* 设置背景颜色 */
border-radius: 8px; /* 设置圆角 */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 添加阴影效果 */
width: 100%; /* 搜索容器宽度占满父容器 */
box-sizing: border-box; /* 确保内边距包含在宽度内 */
`;
// 创建搜索输入框
const partyAuthInput = createSearchInput();
searchContainer.appendChild(partyAuthInput);
// 创建天蓝色的搜索按钮
const searchButton = createButton('搜索', '#4c98fa', () => searchTable(partyAuthInput.value));
searchContainer.appendChild(searchButton);
// 创建灰色的重置按钮
const resetButton = createButton('重置', '#6c757d', () => resetTable(partyAuthInput, tableRows));
searchContainer.appendChild(resetButton);
return searchContainer;
}
// 创建搜索输入框
function createSearchInput() {
const input = document.createElement('input');
input.placeholder = '搜索组织权限';
input.style.cssText = `
width: 300px; /* 设置固定宽度 */
height: 40px; /* 设置固定高度,与按钮一致 */
padding: 0 15px; /* 上下内边距为0,左右为15px */
border: 2px solid #ced4da; /* 加粗边框 */
border-radius: 4px; /* 设置圆角 */
font-size: 16px; /* 字体大小 */
box-sizing: border-box; /* 确保内边距和边框包含在高度内 */
transition: border-color 0.3s; /* 添加过渡效果 */
`;
// 添加聚焦时的边框颜色变化
input.addEventListener('focus', () => {
input.style.borderColor = '#80bdff';
input.style.outline = 'none';
});
input.addEventListener('blur', () => {
input.style.borderColor = '#ced4da';
});
return input;
}
// 创建按钮的通用函数
function createButton(text, backgroundColor, onClick) {
const button = document.createElement('button');
button.innerText = text;
button.style.cssText = `
padding: 0 20px; /* 上下内边距为0,左右为20px */
height: 40px; /* 设置固定高度,与输入框一致 */
background-color: ${backgroundColor};
color: white;
border: none;
border-radius: 4px; /* 设置圆角 */
cursor: pointer;
font-size: 16px; /* 字体大小 */
transition: background-color 0.3s; /* 添加过渡效果 */
`;
// 添加悬停时的背景颜色变化
button.addEventListener('mouseover', () => {
button.style.backgroundColor = shadeColor(backgroundColor, -10);
});
button.addEventListener('mouseout', () => {
button.style.backgroundColor = backgroundColor;
});
button.addEventListener('click', onClick); // 设置点击事件
return button;
}
// 辅助函数:调整颜色深浅
function shadeColor(color, percent) {
const f = parseInt(color.slice(1), 16),
t = percent < 0 ? 0 : 255,
p = Math.abs(percent) / 100,
R = f >> 16,
G = (f >> 8) & 0x00FF,
B = f & 0x0000FF;
const newColor = "#" + (
0x1000000 +
(Math.round((t - R) * p) + R) * 0x10000 +
(Math.round((t - G) * p) + G) * 0x100 +
(Math.round((t - B) * p) + B)
).toString(16).slice(1);
return newColor;
}
// 入口函数
function performing_function() {
// 从 localStorage 获取 RoleList 并解析
const roleList = JSON.parse(localStorage.getItem("RoleList"));
const data = roleList.data.role_list.item;
// 初始化表格
const table = initTable(data);
const tableRows = table.querySelectorAll('tr'); // 获取表格所有行
// 创建外部容器
const container = document.createElement('div');
container.style.cssText = `
width: 100%; /* 容器宽度占满父容器 */
padding: 20px; /* 添加内边距 */
box-sizing: border-box; /* 确保内边距包含在宽度内 */
`;
// 创建搜索栏容器并设置样式
const searchContainer = createSearchContainer(tableRows);
container.appendChild(searchContainer);
// 添加表格到容器
container.appendChild(table);
// 全屏显示内容
createFullScreenDIV(container);
}
})();